<!DOCTYPE html>
<html lang="zh" dir="ltr">

<head prefix="og: http://ogp.me/ns#">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>k8s扩展插件 – Hugo Zzo Theme</title>
    


<script src="/js/enquire.min.dfb99dee1e029d51d6cfb672d847929890b1585402de17f5ed092edd72a688b4.js"></script>

<script defer src="/js/lazysizes.min.31dd6a2d3a1ec0f78a8df007535cf23f03aeb5c70f026e6d6a19dac3b3acc340.js"></script>

<script defer src="/js/fuse.min.94c78ad70b02749822921660cf4e9f0b3701bc0680c421afb784a78228de0275.js"></script>

<script defer src="/js/helper/getParents.min.1618c696be7c98933f9a92677f518b512a74e55bdbb976b09936b4182e93181b.js"></script>

<script defer src="/js/helper/fadeinout.min.93a331f96194789a542f33690bbe4f0c102c7e78ffc018217f5a1c33010bad91.js"></script>

<script defer src="/js/helper/closest.min.js"></script>
  
<script>
  "use strict";

  
  
  if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
  }

  
  if (!String.prototype.includes) {
    String.prototype.includes = function (search, start) {
      'use strict';

      if (search instanceof RegExp) {
        throw TypeError('first argument must not be a RegExp');
      }
      if (start === undefined) { start = 0; }
      return this.indexOf(search, start) !== -1;
    };
  }

  
  Document.prototype.append = Element.prototype.append = function append() {
    this.appendChild(_mutation(arguments));
  };
  function _mutation(nodes) {
    if (!nodes.length) {
      throw new Error('DOM Exception 8');
    } else if (nodes.length === 1) {
      return typeof nodes[0] === 'string' ? document.createTextNode(nodes[0]) : nodes[0];
    } else {
      var
      fragment = document.createDocumentFragment(),
      length = nodes.length,
      index = -1,
      node;

      while (++index < length) {
        node = nodes[index];

        fragment.appendChild(typeof node === 'string' ? document.createTextNode(node) : node);
      }

      return fragment;
    }
  }

  
  if (!String.prototype.startsWith) {
    String.prototype.startsWith = function (searchString, position) {
      position = position || 0;
      return this.indexOf(searchString, position) === position;
    };
  }
  


  document.addEventListener('DOMContentLoaded', function () {
    
    var navCollapseBtn = document.querySelector('.navbar__burger');
    navCollapseBtn ? navCollapseBtn.addEventListener('click', function (e) {
      var navCollapse = document.querySelector('.navbarm__collapse');

      if (navCollapse) {
        var dataOpen = navCollapse.getAttribute('data-open');

        if (dataOpen === 'true') {
          navCollapse.setAttribute('data-open', 'false');
          navCollapse.style.maxHeight = 0;
          navCollapseBtn.classList.remove('is-active');
        } else {
          navCollapse.setAttribute('data-open', 'true');
          navCollapse.style.maxHeight = navCollapse.scrollHeight + "px";
          navCollapseBtn.classList.add('is-active');
        }
      }
    }) : null;
    


    
    var summaryContainer = document.querySelector('.summary__container');
    var searchResult = document.querySelector('.search-result');
    var searchResultCloseBtn = document.querySelector('.search-result__close');
    searchResultCloseBtn ? searchResultCloseBtn.addEventListener('click', function (e) {
      searchResult.setAttribute('data-display', 'none');
      summaryContainer.setAttribute('data-display', 'block');
    }) : null;
    


    
    document.querySelectorAll('.tab') ? 
    document.querySelectorAll('.tab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var tabLinks = elem.querySelectorAll('.tab__link');
      var tabContents = elem.querySelectorAll('.tab__content');
      var ids = [];

      tabLinks && tabLinks.length > 0 ?
      tabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                tabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              tabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    document.querySelectorAll('.codetab') ? 
    document.querySelectorAll('.codetab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var codetabLinks = elem.querySelectorAll('.codetab__link');
      var codetabContents = elem.querySelectorAll('.codetab__content');
      var ids = [];

      codetabLinks && codetabLinks.length > 0 ?
      codetabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                codetabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              codetabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    var gttBtn = document.getElementById("gtt");
    gttBtn.style.display = "none";
    gttBtn.addEventListener('click', function () {
      if (window.document.documentMode) {
        document.documentElement.scrollTop = 0;
      } else {
        scrollToTop(250);
      }
    });

    function scrollToTop(scrollDuration) {
      var scrollStep = -window.scrollY / (scrollDuration / 15);
      var scrollInterval = setInterval(function () {
        if (window.scrollY != 0) {
          window.scrollBy(0, scrollStep);
        }
        else clearInterval(scrollInterval);
      }, 15);
    }

    var scrollFunction = function () {
      if (document.body.scrollTop > 250 || document.documentElement.scrollTop > 250) {
        gttBtn.style.display = "block";
      } else {
        gttBtn.style.display = "none";
      }
    }
    


    
    var expandBtn = document.querySelectorAll('.expand__button');

    for (let i = 0; i < expandBtn.length; i++) {
      expandBtn[i].addEventListener("click", function () {
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          this.querySelector('svg').classList.add('expand-icon__right');
          this.querySelector('svg').classList.remove('expand-icon__down');
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          this.querySelector('svg').classList.remove('expand-icon__right');
          this.querySelector('svg').classList.add('expand-icon__down');
        }
      });
    }
    


    
    var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
    var tocElem = document.querySelector('.toc');
    var tableOfContentsElem = tocElem ? tocElem.querySelector('#TableOfContents') : null;
    var toggleTocElem = document.getElementById('toggle-toc');
    var singleContentsElem = document.querySelector('.single__contents');
    var navbar = document.querySelector('.navbar');
    var tocFlexbox = document.querySelector('.toc__flexbox');
    var tocFlexboxOuter = document.querySelector('.toc__flexbox--outer');
    var expandContents = document.querySelectorAll('.expand__content');
    var boxContents = document.querySelectorAll('.box');
    var notAllowedTitleIds = null;

    
    var tocFolding = JSON.parse("null");
    
    var tocLevels = JSON.parse("null");
    
    if (tocLevels) {
      tocLevels = tocLevels.toString();
    } else {
      tocLevels = "h1, h2, h3, h4, h5, h6";
    }

    
    singleContentsElem && singleContentsElem.querySelectorAll(".tab") ?
    singleContentsElem.querySelectorAll(".tab").forEach(function (elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    expandContents ? expandContents.forEach(function(elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    boxContents ? boxContents.forEach(function(elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    window.onscroll = function () {
      scrollFunction();
      
      var st = window.pageYOffset || document.documentElement.scrollTop;
      if (st > lastScrollTop) { 
        if (st < 250) {
          gttBtn.style.display = "none";
        } else {
          gttBtn.style.display = "block";
        }

        if (st < 45) {
          return null;
        }
        
        if (!navbar.classList.contains('navbar--hide')) {
          navbar.classList.add('navbar--hide');
        } else if (navbar.classList.contains('navbar--show')) {
          navbar.classList.remove('navbar--show');
        }

        if (singleContentsElem) {
          if (singleContentsElem.querySelectorAll(tocLevels).length > 0) {
            singleContentsElem.querySelectorAll(tocLevels).forEach(function (elem) {
              if (toggleTocElem && !toggleTocElem.checked) {
                return null;
              }

              if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
                return null;
              }
              
              if (document.documentElement.scrollTop >= elem.offsetTop) {
                if (tableOfContentsElem) {
                  var id = elem.getAttribute('id');
                  tocElem.querySelectorAll('a').forEach(function (elem) {
                    elem.classList.remove('active');
                  });
                  tocElem.querySelector('a[href="#' + id + '"]') ?
                    tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;

                  if (false === tocFolding) {
                    
                  } else {
                    tableOfContentsElem.querySelectorAll('ul') ?
                      tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
                        rootUl.querySelectorAll('li').forEach(function (liElem) {
                          liElem.querySelectorAll('ul').forEach(function (ulElem) {
                            ulElem.style.display = 'none';
                          });
                        });
                      }) : null;
                  }

                  var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
                  if (curElem && curElem.nextElementSibling) {
                    curElem.nextElementSibling.style.display = 'block';
                  }
                  getParents(curElem, 'ul') ?
                    getParents(curElem, 'ul').forEach(function (elem) {
                      elem.style.display = 'block';
                    }) : null;
                }
              }
            });
          } else {
            if (tocFlexbox) {
              tocFlexbox.setAttribute('data-position', '');
              if (!tocFlexbox.classList.contains('hide')) {
                tocFlexbox.classList.add('hide');
              }
            }
            if (tocFlexboxOuter) {
              tocFlexboxOuter.setAttribute('data-position', '');
              if (!tocFlexboxOuter.classList.contains('hide')) {
                tocFlexboxOuter.classList.add('hide');
              }
            }
          }
        }
      } else { 
        if (st < 250) {
          gttBtn.style.display = "none";
        }

        if (navbar.classList.contains('navbar--hide')) {
          navbar.classList.remove('navbar--hide');
        } else if (!navbar.classList.contains('navbar--show')) {
          navbar.classList.add('navbar--show');
        }

        if (singleContentsElem) {
          if (singleContentsElem.querySelectorAll(tocLevels).length > 0) {
            singleContentsElem.querySelectorAll(tocLevels).forEach(function (elem) {
              if (toggleTocElem && !toggleTocElem.checked) {
                return null;
              }
              
              if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
                return null;
              }

              if (document.documentElement.scrollTop >= elem.offsetTop) {
                if (tableOfContentsElem) {
                  var id = elem.getAttribute('id');
                  tocElem.querySelectorAll('a').forEach(function (elem) {
                    elem.classList.remove('active');
                  });
                  tocElem.querySelector('a[href="#' + id + '"]') ?
                    tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;

                  if (false === tocFolding) {
                    
                  } else {
                    tableOfContentsElem.querySelectorAll('ul') ?
                      tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
                        rootUl.querySelectorAll('li').forEach(function (liElem) {
                          liElem.querySelectorAll('ul').forEach(function (ulElem) {
                            ulElem.style.display = 'none';
                          });
                        });
                      }) : null;
                  }

                  var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
                  if (curElem && curElem.nextElementSibling) {
                    curElem.nextElementSibling.style.display = 'block';
                  }
                  getParents(curElem, 'ul') ?
                    getParents(curElem, 'ul').forEach(function (elem) {
                      elem.style.display = 'block';
                    }) : null;
                }
              }
            });
          } else {
            if (tocFlexbox && !tocFlexbox.classList.contains('hide')) {
              tocFlexbox.classList.add('hide');
            }
            if (tocFlexboxOuter && !tocFlexboxOuter.classList.contains('hide')) {
              tocFlexboxOuter.classList.add('hide');
            }
          }
          
        }

        if (tableOfContentsElem && document.documentElement.scrollTop < 250) {
          if (false === tocFolding) {

          } else {
            tableOfContentsElem.querySelector('ul') ?
              tableOfContentsElem.querySelector('ul').querySelectorAll('li').forEach(function (liElem) {
                liElem.querySelectorAll('ul').forEach(function (ulElem) {
                  ulElem.style.display = 'none';
                });
              }) : null;
          }
        }
      }
      lastScrollTop = st <= 0 ? 0 : st;
    };
  


  
    var localTheme = localStorage.getItem('theme');
    var rootEleme = document.getElementById('root');
    var selectThemeElem = document.querySelectorAll('.select-theme');
    var selectThemeItemElem = document.querySelectorAll('.select-theme__item');

    var setMetaColor = function(themeColor) {
      var metaMsapplicationTileColor = document.getElementsByName('msapplication-TileColor')[0];
      var metaThemeColor = document.getElementsByName('theme-color')[0];
      var metaMsapplicationNavbuttonColor = document.getElementsByName('msapplication-navbutton-color')[0];
      var metaAppleMobileWebAappStatusBarStyle = document.getElementsByName('apple-mobile-web-app-status-bar-style')[0];

      if (themeColor.includes('dark')) {
        metaMsapplicationTileColor.setAttribute('content', '#fcfcfa');
        metaThemeColor.setAttribute('content', '#403E41');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#403E41');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#403E41');
      } else if (themeColor.includes('light')) {
        metaMsapplicationTileColor.setAttribute('content', '#555');
        metaThemeColor.setAttribute('content', '#eee');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#eee');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#eee');
      } else if (themeColor.includes('hacker')) {
        metaMsapplicationTileColor.setAttribute('content', '#e3cd26');
        metaThemeColor.setAttribute('content', '#252526');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#252526');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#252526');
      } else if (themeColor.includes('solarized')) {
        metaMsapplicationTileColor.setAttribute('content', '#d3af86');
        metaThemeColor.setAttribute('content', '#51412c');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#51412c');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#51412c');
      } else if (themeColor.includes('kimbie')) {
        metaMsapplicationTileColor.setAttribute('content', '#586e75');
        metaThemeColor.setAttribute('content', '#eee8d5');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#eee8d5');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#eee8d5');
      } 
    }
    
    if (localTheme) {
      selectThemeItemElem ? 
      selectThemeItemElem.forEach(function (elem) {
        if (elem.text.trim() === localTheme) {
          elem.classList.add('is-active');
        } else {
          elem.classList.remove('is-active');
        }
      }) : null;

      setMetaColor(localTheme);
    } else {
      setMetaColor(rootEleme.className);
    }

    selectThemeItemElem ? 
    selectThemeItemElem.forEach(function (v, i) {
      v.addEventListener('click', function (e) {
        var selectedThemeVariant = e.target.text.trim();
        localStorage.setItem('theme', selectedThemeVariant);
        setMetaColor(selectedThemeVariant);

        rootEleme.removeAttribute('class');
        rootEleme.classList.add('theme__' + selectedThemeVariant);
        selectThemeElem.forEach(function(rootElem) {
          rootElem.querySelectorAll('a').forEach(function (elem) {
            if (elem.classList) {
              if (elem.text.trim() === selectedThemeVariant) {
                if (!elem.classList.contains('is-active')) {
                  elem.classList.add('is-active');
                }
              } else {
                if (elem.classList.contains('is-active')) {
                  elem.classList.remove('is-active');
                }
              }
            }
          });
        });

        if (window.mermaid) {
          if (selectedThemeVariant === "dark" || selectedThemeVariant === "hacker") {
            mermaid.initialize({ theme: 'dark' });
            location.reload();
          } else {
            mermaid.initialize({ theme: 'default' });
            location.reload();
          }
        }

        var utterances = document.getElementById('utterances');
        if (utterances) {
          utterances.querySelector('iframe').contentWindow.postMessage({
            type: 'set-theme',
            theme: selectedThemeVariant === "dark" || selectedThemeVariant === "hacker" ? 'photon-dark' : selectedThemeVariant === 'kimbie' ? 'github-dark-orange' : 'github-light',
          }, 'https://utteranc.es');
        }

        var twitterCards = document.querySelectorAll('.twitter-timeline');
        if (twitterCards) {
          window.postMessage({
            type: 'set-twitter-theme',
            theme: selectedThemeVariant === 'light' || selectedThemeVariant === 'solarized' ? 'light' : 'dark',
          });
        }
      });
    }) : null;
  


  
    
    var permalink = JSON.parse("\"http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6/\"");
    var searchResults = null;
    var searchMenu = null;
    var searchText = null;
    
    
    var enableSearchHighlight = JSON.parse("true");
    
    var searchResultPosition = JSON.parse("\"main\"");
    
    var sectionType = JSON.parse("\"linux\"");

    var fuse = null;

    (function initFuse() {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', permalink + "index.json");
      xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
      xhr.onload = function () {
        if (xhr.status === 200) {
          fuse = new Fuse(JSON.parse(xhr.response.toString('utf-8')), {
            keys: sectionType.includes('publication') ? ['title', 'abstract'] : ['title', 'description', 'content'],
            includeMatches: enableSearchHighlight,
            shouldSort: true,
            threshold: 0.4,
            location: 0,
            distance: 100,
            maxPatternLength: 32,
            minMatchCharLength: 1,
          });
          window.fuse = fuse;
        }
        else {
          console.error('[' + xhr.status + ']Error:', xhr.statusText);
        }
      };
      xhr.send();
    })();

    function makeLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      
      var a = document.createElement('a');
      a.innerHTML = obj.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.permalink);

      var descDiv = document.createElement('div');
      descDiv.setAttribute('class', 'search-result__item--desc');
      if (obj.description) {
        descDiv.innerHTML = obj.description;
      } else if (obj.content) {
        descDiv.innerHTML = obj.content.substring(0, 225);
      }
      
      li.appendChild(a);
      li.appendChild(descDiv);
      ulElem.appendChild(li);
    }

    function makeHighlightLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      var descDiv = null;

      var a = document.createElement('a');
      a.innerHTML = obj.item.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.item.uri);

      if (obj.matches && obj.matches.length) {
        for (var i = 0; i < obj.matches.length; i++) {
          if ('title' === obj.matches[i].key) {
            a = document.createElement('a');
            a.innerHTML = generateHighlightedText(obj.matches[i].value, obj.matches[i].indices);
            a.setAttribute('class', 'search-result__item--title');
            a.setAttribute('href', obj.item.uri);
          }
          
          if ('description' === obj.matches[i].key) {
            descDiv = document.createElement('div');
            descDiv.setAttribute('class', 'search-result__item--desc');
            descDiv.innerHTML = generateHighlightedText(obj.item.description, obj.matches[i].indices);
          } else if ('content' === obj.matches[i].key) {
            if (!descDiv) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = generateHighlightedText(obj.item.content.substring(0, 150), obj.matches[i].indices);
            }
          } else {
            if (obj.item.description) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.description;
            } else {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.content.substring(0, 150);
            }
          }
        }

        li.appendChild(a);
        if (descDiv) {
          li.appendChild(descDiv);
        }
        if (li) {
          ulElem.appendChild(li);
        }
      }
    }

    function renderSearchResultsSide(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dropdown is-active');
      
      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dropdown-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          a.setAttribute('href', result.uri);
          a.setAttribute('class', 'dropdown-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.title;
          titleDiv.setAttribute('class', 'menu-item__title');

          var descDiv = document.createElement('div');
          descDiv.setAttribute('class', 'menu-item__desc');
          if (result.description) {
            descDiv.innerHTML = result.description;
          } else if (result.content) {
            descDiv.innerHTML = result.content.substring(0, 150);
          }

          li.appendChild(titleDiv);
          li.appendChild(descDiv);
          ul.appendChild(a);
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dropdown-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      
      searchMenu.appendChild(ul);
    }

    function renderSearchHighlightResultsSide(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dropdown is-active');

      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dropdown-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.setAttribute('class', 'dropdown-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'menu-item__title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'menu-item__desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dropdown-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      searchMenu.appendChild(ul);
    }

    function renderSearchResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var content = document.createElement('div');
      content.setAttribute('class', 'mobile-search__content');

      if (results.length > 0) {
        results.forEach(function (result) {
          var item = document.createElement('a');
          item.setAttribute('href', result.uri);
          item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + result.title + '</div><div class="mobile-search__item--desc">' + (result.description ? result.description : result.content) + '</div></div>';
          content.appendChild(item);
        });
      } else {
        var item = document.createElement('span');
        content.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(content);      
    }

    function renderSearchHighlightResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var ul = document.createElement('div');
      ul.setAttribute('class', 'mobile-search__content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.appendChild(li);
          li.setAttribute('class', 'mobile-search__item');

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'mobile-search__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'mobile-search__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var item = document.createElement('span');
        ul.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(ul);
    }

    function generateHighlightedText(text, regions) {
      if (!regions) {
        return text;
      }

      var content = '', nextUnhighlightedRegionStartingIndex = 0;

      regions.forEach(function(region) {
        if (region[0] === region[1]) {
          return null;
        }
        
        content += '' +
          text.substring(nextUnhighlightedRegionStartingIndex, region[0]) +
          '<span class="search__highlight">' +
            text.substring(region[0], region[1] + 1) +
          '</span>' +
        '';
        nextUnhighlightedRegionStartingIndex = region[1] + 1;
      });

      content += text.substring(nextUnhighlightedRegionStartingIndex);

      return content;
    };

    var searchElem = document.getElementById('search');
    var searchMobile = document.getElementById('search-mobile');
    var searchResultsContainer = document.getElementById('search-results');

    searchElem ?
    searchElem.addEventListener('input', function(e) {
      if (!e.target.value | window.innerWidth < 770) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      
      if (searchResultPosition === "main") {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsMain(searchText, results);
        } else {
          renderSearchResultsMain(searchText, results);
        }
      } else {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsSide(searchText, results);
        } else {
          renderSearchResultsSide(searchText, results);
        }
        
        var dropdownItems = searchResultsContainer.querySelectorAll('.dropdown-item');
        dropdownItems ? dropdownItems.forEach(function(item) {
          item.addEventListener('mousedown', function(e) {
            e.target.click();
          });
        }) : null;
      }
    }) : null;

    searchElem ? 
    searchElem.addEventListener('blur', function() {
      if (window.innerWidth < 770) {
        return null;
      }
      searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('click', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }
      if (!e.target.value) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (searchResultPosition === "main") {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsMain(searchText, results);
        } else {
          renderSearchResultsMain(searchText, results);
        }
      } else{
        if (enableSearchHighlight) {
          renderSearchHighlightResultsSide(searchText, results);
        } else {
          renderSearchResultsSide(searchText, results);
        }

        var dropdownItems = searchResultsContainer.querySelectorAll('.dropdown-item');
        dropdownItems ? dropdownItems.forEach(function (item) {
          item.addEventListener('mousedown', function (e) {
            e.target.click();
          });
        }) : null;
      }
    }) : null;

    var searchMenuElem = document.getElementById("search-menu");
    var activeItem = document.querySelector('#search-menu .dropdown-item.is-active');
    var activeIndex = null;
    var items = null;
    var searchContainerMaxHeight = 350;

    searchElem ? 
    searchElem.addEventListener('keydown', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }

      if (e.key === 'Escape') {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      }

      var items = document.querySelectorAll('#search-menu .dropdown-item');
      var keyCode = e.which || e.keyCode;

      if (!items || !items.length) {
        return null;
      }
      
      if (e.key === 'ArrowDown' || keyCode === 40) {
        if (activeIndex === null) {
          activeIndex = 0;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
        }
        items[activeIndex].classList.add('is-active');

        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel > 0) {
          document.querySelector(".search-content").scrollTop += items[activeIndex].getBoundingClientRect().height;
        } else if (activeIndex === 0) {
          document.querySelector(".search-content").scrollTop = 0;
        }
      } else if (e.key === 'ArrowUp' || keyCode === 38) {
        if (activeIndex === null) {
          activeIndex = items.length - 1;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
        }
        items[activeIndex].classList.add('is-active');
        
        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel < 0) {
          document.querySelector(".search-content").scrollTop -= items[activeIndex].getBoundingClientRect().height;
        } else {
          document.querySelector(".search-content").scrollTop = overflowedPixel + items[activeIndex].getBoundingClientRect().height;
        }
      } else if (e.key === 'Enter' || keyCode === 13) {
        if (items[activeIndex] && items[activeIndex].getAttribute('href')) {
          location.href = items[activeIndex].getAttribute('href');
        }
      } else if (e.key === 'Escape' || keyCode === 27) {
        e.target.value = null;
        if (searchResults) {
          searchResults.classList.remove('is-active');
        }
      }
    }) : null;

    searchMobile ? 
    searchMobile.addEventListener('input', function(e) {
      if (!e.target.value) {
        let wrap = document.getElementById('search-mobile-results');
        while (wrap.firstChild) {
          wrap.removeChild(wrap.firstChild);
        }
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      renderSearchResultsMobile(searchText, results);
      if (enableSearchHighlight) {
        renderSearchHighlightResultsMobile(searchText, results);
      } else {
        renderSearchResultsMobile(searchText, results);
      }
    }) : null;
  


  
    var mobileSearchInputElem = document.querySelector('#search-mobile');
    var mobileSearchClassElem = document.querySelector('.mobile-search');
    var mobileSearchBtnElem = document.querySelector('#mobileSearchBtn');
    var mobileSearchCloseBtnElem = document.querySelector('#search-mobile-close');
    var mobileSearchContainer = document.querySelector('#search-mobile-container');
    var mobileSearchResultsElem = document.querySelector('#search-mobile-results');
    var htmlElem = document.querySelector('html');

    if (mobileSearchClassElem) {
      mobileSearchClassElem.style.display = 'none';
    }

    mobileSearchBtnElem ? 
    mobileSearchBtnElem.addEventListener('click', function () {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'block';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.focus();
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'hidden';
      }
    }) : null;

    mobileSearchCloseBtnElem ? 
    mobileSearchCloseBtnElem.addEventListener('click', function() {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'none';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.value = '';
      }
      
      if (mobileSearchResultsElem) {
        while (mobileSearchResultsElem.firstChild) {
          mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
        }
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'visible';
      }
    }) : null;

    mobileSearchInputElem ?
    mobileSearchInputElem.addEventListener('keydown', function(e) {
      var keyCode = e.which || e.keyCode;
      if (e.key === 'Escape' || keyCode === 27) {
        if (mobileSearchContainer) {
          mobileSearchContainer.style.display = 'none';
        }
        
        if (mobileSearchInputElem) {
          mobileSearchInputElem.value = '';
        }

        if (mobileSearchResultsElem) {
          while (mobileSearchResultsElem.firstChild) {
            mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
          }
        }
        if (htmlElem) {
          htmlElem.style.overflowY = 'visible';
        }
      }
    }) : null;
  


  
    function renderSearchResultsMain(searchText, results) {
      var searchBody = document.querySelector('.search-result__body');
      var originUl = searchBody.querySelector('ul');
      var ul = document.createElement('ul');
      
      if (!searchText) {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      } else if (results) {
        if (results && results.length) {
          results.forEach(function (result) {
            makeLi(ul, result);
          });

          searchResult ? searchResult.setAttribute('data-display', 'block') : null;
          summaryContainer ? summaryContainer.setAttribute('data-display', 'none') : null;
        }
      }

      originUl.parentNode.replaceChild(ul, originUl);
    }

    function renderSearchHighlightResultsMain(searchText, results) {
      var searchBody = document.querySelector('.search-result__body');
      var originUl = searchBody.querySelector('ul');
      var ul = document.createElement('ul');

      if (!searchText) {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      } else if (results) {
        if (results && results.length) {
          results.forEach(function (result) {
            makeHighlightLi(ul, result);
          });

          searchResult ? searchResult.setAttribute('data-display', 'block') : null;
          summaryContainer ? summaryContainer.setAttribute('data-display', 'none') : null;
        }
      }

      originUl.parentNode.replaceChild(ul, originUl);
    }
  
  });
</script>    
    


<link rel="stylesheet" href="/css/main.min.css">


    
<meta name="description" content="" />


<meta name="keywords" content="虚拟化">

<meta name="created" content="2019-11-07T02:00:00&#43;0000">
<meta name="modified" content="2019-11-07T02:00:00&#43;0000">
<meta property="article:published_time" content="2019-11-07T02:00:00&#43;0000">

<meta name="author" content="月冰升">


<meta property="og:site_name" content="Hugo Zzo Theme">
<meta property="og:title" content="k8s扩展插件">
<meta property="og:url" content="http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6/">
<meta property="og:type" content="article">
<meta property="og:description" content="">

<meta name="generator" content="Hugo 0.68.3" />
<meta name="msapplication-TileColor" content="#fff">

<meta name="theme-color" content="#fff">

<meta name="msapplication-navbutton-color" content="#fff">

<meta name="apple-mobile-web-app-status-bar-style" content="#fff">

<link rel="canonical" href="http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6/">

<link rel="manifest" href="/manifest.json">

  
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
  <link rel="icon" href="/favicon.png" sizes="any" type="image/png" />
  


    <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebPage",
    "headline": "k8s扩展插件",
    "datePublished": "2019-11-07T02:00:00Z",
    "dateModified": "2019-11-07T02:00:00Z",
    "url" : "http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6/",
    "description": ,
    "keywords": ["虚拟化"],
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "http://shaddy.gitee.io/"
    },
    "publisher": {
      "@type": "Organization",
      "name": "Hugo Zzo Theme",
      "url": "http://shaddy.gitee.io/"
    }
  }
</script>

    
  
  







    
</head>

<body id="root" class="theme__dark">
    <script>
        var localTheme = localStorage.getItem('theme');
        if (localTheme) {
            document.getElementById('root').className = 'theme__' + localTheme;
        }
    </script>
    <div id="container">
        





        <div class="wrapper" data-type="linux" data-kind="page">
            <nav class="navbar" role="navigation" aria-label="main navigation" data-dir="ltr">
  <div class="navbar__brand">
    
    <a href="/zh/" title="主页" rel="home" class="navbar__logo-link">
      <img src="/logo.png" alt="Home" class="navbar__logo">
    </a>
    
    
      <a href="/zh/" title="主页" rel="home" class="navbar__title-link">
        <h6 class="navbar__title">HOME</h6>
      </a>
    
  </div>

  
<div class="theme theme-mobile" data-ani="true">
  <div class="dropdown">
    <button class="dropdown-trigger navbar__slide-down" aria-label="Select Theme Button" style="" data-ani="true">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M24 0H0v24h24V0z"/><path fill="currentColor" d="M6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58s4.1-.78 5.66-2.34c3.12-3.12 3.12-8.19 0-11.31l-4.95-4.95c-.39-.39-1.02-.39-1.41 0L6.34 7.93zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></svg>      
    </button>
    <div class="dropdown-content select-theme">
      
        
        <a href="#" class="dropdown-item select-theme__item is-active">
          dark
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          light
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          hacker
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          solarized
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          kimbie
        </a>
        
      
    </div>
  </div>
</div>


<div id="mobileSearchBtn" class="mobile-search__btn" data-ani="true">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</div>

<div id="search-mobile-container" class="mobile-search hide" data-dir="ltr">
  <div class="mobile-search__top">
    <input id="search-mobile" type="text" aria-label="Mobile Search" placeholder="搜索" class="mobile-search__top--input"/>
    <div id="search-mobile-close" class="mobile-search__top--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z"/></svg>
    </div>
  </div>
  <div id="search-mobile-results" class="mobile-search__body">
    
  </div>
</div>


<a role="button" class="navbar__burger" aria-label="menu" aria-expanded="false"
  data-ani="true">
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
</a>
<div class="navbarm__collapse" data-open="false">
  <ul dir="ltr">
    
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/zh/about">about</a>
        </li>
      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/zh/archive">archive</a>
        </li>
      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/zh/gallery">
            gallery
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/></svg>
          </a>
        </li>

        
          <li class="navbarm__menu--item navbarm__menu--subitem">
            <a href="/zh/gallery/cartoon">cartoon</a>
          </li>
        
          <li class="navbarm__menu--item navbarm__menu--subitem">
            <a href="/zh/gallery/photo">photo</a>
          </li>
        

      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/zh/posts">posts</a>
        </li>
      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/zh/notes">notes</a>
        </li>
      
      
    

    
  </ul>
</div>
  <div class="navbar__menu">
  
<div class="theme" data-ani="true">
  <div class="dropdown">
    <button class="dropdown-trigger navbar__slide-down" aria-label="Select Theme Button" data-ani="true">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M24 0H0v24h24V0z"/><path fill="currentColor" d="M6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58s4.1-.78 5.66-2.34c3.12-3.12 3.12-8.19 0-11.31l-4.95-4.95c-.39-.39-1.02-.39-1.41 0L6.34 7.93zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></svg>      
    </button>
    <div class="dropdown-content select-theme">
      
        
        <a href="#" class="dropdown-item select-theme__item is-active">
          dark
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          light
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          hacker
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          solarized
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          kimbie
        </a>
        
      
    </div>
  </div>
</div>

  
  
  
  
  
  
  
  <a href="/zh/about" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">about</a>
  
  
  
  
  
  
  
  <a href="/zh/archive" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">archive</a>
  
  
  
  
  
  
  
  <div class="navbar__dropdown navbar__slide-down" data-ani="true">
    <a href="/zh/gallery" class="navbar__menu-item "
      dir="ltr">
      gallery
      <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/></svg>
    </a>
    <div class="navbar__dropdown--content">
      
      <a href="/zh/gallery/cartoon" class="navbar__dropdown--item" dir="ltr">cartoon</a>
      
      <a href="/zh/gallery/photo" class="navbar__dropdown--item" dir="ltr">photo</a>
      
    </div>
  </div>
  
  
  
  
  
  
  
  <a href="/zh/posts" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">posts</a>
  
  
  
  
  
  
  
  <a href="/zh/notes" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">notes</a>
  
  
</div>
</nav>
            
            

<main class="single__main main-main">
  
    <nav class="breadcrumb hide" aria-label="breadcrumbs">
  <script>document.querySelector('.breadcrumb').classList.remove('hide')</script>
  <ol>
    
  
  
  
  
  
  <li >
    
      <a href="http://shaddy.gitee.io/zh/" class="capitalize">Hugo Zzo Theme</a>
    
  </li>
  
  
  <li >
    
      <a href="http://shaddy.gitee.io/zh/linux/" class="capitalize">Linuxes</a>
    
  </li>
  
  
  <li  class="is-active" >
    
      <span>k8s扩展插件</span>
    
  </li>
  
  </ol>
  
</nav>
  
  
  <div class="single ">
    <div class="single__nojs">Please enable Javascript to view the contents</div>
    <script>document.querySelector('.single').classList.remove('hide'); document.querySelector('.single__nojs').classList.add('hide');</script>
    <h2 class="single__title" data-ani="true">k8s扩展插件</h2>
    <div class="single__meta">
      
<div class="single__infos">
  <time class="single__info" title="创建日期">📅&nbsp;2019年11月07日 </time>
  
  &nbsp;&middot;&nbsp; <span class="single__info" title="阅读时长"> ☕&nbsp;14&nbsp;分钟 </span>
  
  <span class="single__info">
    
  </span>
</div>
      
<ul class="single__tags caption">
  
  🏷️
  

  <li><a href="http://shaddy.gitee.io/zh/tags/%E8%99%9A%E6%8B%9F%E5%8C%96/" class="single__tag" title="虚拟化">#虚拟化</a></li>

</ul>
    </div>
    <article class="single__contents" data-dir="ltr" data-ani="true">
      
      <blockquote>
<p>k8s扩展插件</p>
</blockquote>
<!-- more -->
<h3 id="flannel在docker中安装">flannel在docker中安装</h3>
<h4 id="flannel结点步骤">flannel结点步骤</h4>
<pre><code>登录192.168.106.117 ,其他结点类似。
https://github.com/coreos/flannel/releases地址
[root@managementa ~] wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
此版本的flanneld只支持etcd的v2版本的api，在此注意。
[root@managementa ~]# tar -xzvf flannel-v0.11.0-linux-amd64.tar.gz 
[root@managementa ~]# mv flanneld /usr/local/docker/
[root@managementa ~]# rm -fr README.md 
[root@managementa ~]# mv mk-docker-opts.sh /usr/local/docker/
[root@managementa ~]# rm -fr flannel-v0.11.0-linux-amd64.tar.gz
[root@managementa ~]# vim /etc/sysconfig/flanneld
FLANNEL_ETCD=&quot;http://192.168.106.237:2379&quot;
FLANNEL_ETCD_KEY=&quot;/flannel/network&quot;
FLANNEL_OPTIONS=&quot;-ip-masq=true -v=0&quot;
FLANNEL_IFACE=&quot;192.168.106.117&quot; #网卡 eth0 或IP
-ip-masq=true 这个参数的目的是让flannel进行ip伪装，而不让docker进行ip伪装。这么做的原因是如果docker进行ip伪装，流量再从flannel出去，其他host上看到的source ip就是flannel的网关ip，而不是docker容器的ip
-v 日志级别
[root@managementa ~]# vim /usr/lib/systemd/system/flanneld.service 
[Unit]
Description=Flanneld server
After=network.target
After=network-online.target
Wants=network-online.target
Before=docker.service
 
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/flanneld
ExecStart=/usr/local/docker/flanneld -etcd-endpoints=${FLANNEL_ETCD} -iface=${FLANNEL_IFACE} -etcd-prefix=${FLANNEL_ETCD_KEY} $FLANNEL_OPTIONS
Restart=on-failure
 
[Install]
WantedBy=multi-user.target

</code></pre><h4 id="flannel对应etcd配置">flannel对应etcd配置</h4>
<pre><code>登录192.168.106.237
#向etcd 写入网段配置
[root@managementa ~] export ETCDCTL_API=2
[root@managementa ~] etcdctl --endpoint http://192.168.106.237:2379 mk /flannel/network/config '{&quot;Network&quot;: &quot;172.17.0.1/16&quot;,&quot;SubnetMin&quot;: &quot;172.17.0.0&quot;, &quot;SubnetMax&quot;: &quot;172.17.254.0&quot;,&quot;Backend&quot;:{&quot;Type&quot;:&quot;vxlan&quot;}}' 
{&quot;Network&quot;: &quot;172.17.0.1/16&quot;,&quot;SubnetMin&quot;: &quot;172.17.0.0&quot;, &quot;SubnetMax&quot;: &quot;172.17.254.0&quot;,&quot;Backend&quot;:{&quot;Type&quot;:&quot;vxlan&quot;}}
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 ls
/flannel
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 ls /flannel
/flannel/network
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 ls /flannel/network
/flannel/network/config
/flannel/network/subnets
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 ls /flannel/network/config
/flannel/network/config
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 get /flannel/network/config
{&quot;Network&quot;: &quot;172.17.0.1/16&quot;,&quot;SubnetMin&quot;: &quot;172.17.0.0&quot;, &quot;SubnetMax&quot;: &quot;172.17.254.0&quot;,&quot;Backend&quot;:{&quot;Type&quot;:&quot;vxlan&quot;}}
[root@sdw3 ~]# etcdctl --endpoints=http://192.168.106.237:2379 ls /flannel/network/subnets 
/flannel/network/subnets/172.17.63.0-24


错误解决
 Couldn't fetch network config: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint.
Nov 11 10:53:42 managementa flanneld: timed out
flannel的0.11版本临时不支持etcd3.4，并且不支持3版本的api。 下载etcd 3.3.17
https://github.com/etcd-io/etcd/releases/download/v3.3.17/etcd-v3.3.17-linux-amd64.tar.gz
</code></pre><h4 id="结点其他配置">结点其他配置</h4>
<pre><code>[root@managementa ~] iptables -F
[root@managementa ~] iptables -X
[root@managementa ~] iptables -t nat -F
[root@managementa ~] iptables -t nat -X
[root@managementa ~] iptables -t mangle -F
[root@managementa ~] iptables -t mangle -X
[root@managementa ~] iptables -t raw -F
[root@managementa ~] iptables -t raw -X
[root@managementa ~] iptables -t security -F
[root@managementa ~] iptables -t security -X
[root@managementa ~] iptables -P INPUT ACCEPT
[root@managementa ~] iptables -P FORWARD ACCEPT
[root@managementa ~] iptables -P OUTPUT ACCEPT
**只刷新nat表**

[root@managementa ~]# systemctl daemon-reload
[root@managementa ~]# systemctl stop docker
[root@managementa ~]# systemctl stop flanneld
[root@managementa ~]# systemctl enable flanneld
Created symlink from /etc/systemd/system/multi-user.target.wants/flanneld.service to /usr/lib/systemd/system/flanneld.service.
[root@managementa ~]# systemctl start flanneld
[root@managementa ~]# mk-docker-opts.sh 
[root@managementa ~]# cat /run/docker
docker/          docker_opts.env  
[root@managementa ~]# cat /run/docker_opts.env 
DOCKER_OPT_BIP=&quot;--bip=172.17.63.1/24&quot;
DOCKER_OPT_IPMASQ=&quot;--ip-masq=false&quot;
DOCKER_OPT_MTU=&quot;--mtu=1450&quot;
DOCKER_OPTS=&quot; --bip=172.17.63.1/24 --ip-masq=false --mtu=1450&quot;
按照上面的配置修改，如下：
[root@managementa ~]# vi /etc/docker/daemon.json 
{
    &quot;registry-mirror&quot;:[&quot;http://192.168.106.117&quot;],
    &quot;insecure-registries&quot;:[&quot;192.168.106.117&quot;],
    &quot;bip&quot;:&quot;172.17.63.1/24&quot;,
    &quot;ip-masq&quot;:false,
    &quot;mtu&quot;:1450

}
[root@managementa ~]# curl http://192.168.106.237:2379/v2/keys/flannel/network/subnets | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   383  100   383    0     0   333k      0 --:--:-- --:--:-- --:--:--  374k
{
    &quot;action&quot;: &quot;get&quot;,
    &quot;node&quot;: {
        &quot;createdIndex&quot;: 9,
        &quot;dir&quot;: true,
        &quot;key&quot;: &quot;/flannel/network/subnets&quot;,
        &quot;modifiedIndex&quot;: 9,
        &quot;nodes&quot;: [
            {
                &quot;createdIndex&quot;: 10,
                &quot;expiration&quot;: &quot;2019-11-12T06:21:24.956806947Z&quot;,
                &quot;key&quot;: &quot;/flannel/network/subnets/172.17.63.0-24&quot;,
                &quot;modifiedIndex&quot;: 10,
                &quot;ttl&quot;: 85737,
                &quot;value&quot;: &quot;{\&quot;PublicIP\&quot;:\&quot;192.168.106.117\&quot;,\&quot;BackendType\&quot;:\&quot;vxlan\&quot;,\&quot;BackendData\&quot;:{\&quot;VtepMAC\&quot;:\&quot;5e:8e:c4:02:e6:c8\&quot;}}&quot;
            }
        ]
    }
}
[root@managementa ~]# systemctl restart docker
~      
</code></pre><h3 id="k8s-ca证书部署">k8s ca证书部署</h3>
<pre><code>下载 cfssl 工具：https://pkg.cfssl.org/
[root@managementa conf]# curl -s -L -o /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
[root@managementa conf]# curl -s -L -o /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
[root@managementa conf]# curl -s -L -o /bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
[root@managementa conf]# chmod +x /bin/cfssl*
[root@managementa conf]# mkdir /root/ssl
[root@managementa conf]# cd /root/ssl
[root@managementa ssl]# cat &gt; ca-config.json &lt;&lt; EOF
{
  &quot;signing&quot;: {
    &quot;default&quot;: {
      &quot;expiry&quot;: &quot;87600h&quot;
    },
    &quot;profiles&quot;: {
      &quot;kubernetes&quot;: {
        &quot;usages&quot;: [
            &quot;signing&quot;,
            &quot;key encipherment&quot;,
            &quot;server auth&quot;,
            &quot;client auth&quot;
        ],
        &quot;expiry&quot;: &quot;87600h&quot;
      }
    }
  }
}
EOF

[root@managementa ssl]# cat &gt; ca-csr.json &lt;&lt; EOF
{
  &quot;CN&quot;: &quot;kubernetes&quot;,
  &quot;key&quot;: {
    &quot;algo&quot;: &quot;rsa&quot;,
    &quot;size&quot;: 2048
  },
  &quot;names&quot;: [
    {
      &quot;C&quot;: &quot;CN&quot;,
      &quot;ST&quot;: &quot;BeiJing&quot;,
      &quot;L&quot;: &quot;BeiJing&quot;,
      &quot;O&quot;: &quot;k8s&quot;,
      &quot;OU&quot;: &quot;System&quot;
    }
  ]
}
EOF
[root@managementa ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2019/11/13 15:24:05 [INFO] generating a new CA key and certificate from CSR
2019/11/13 15:24:05 [INFO] generate received request
2019/11/13 15:24:05 [INFO] received CSR
2019/11/13 15:24:05 [INFO] generating key: rsa-2048
2019/11/13 15:24:05 [INFO] encoded CSR
2019/11/13 15:24:05 [INFO] signed certificate with serial number 714375892951147589454567376836425223244252998471
[root@managementa ssl]# ls ca*
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem



[root@managementa ssl]# cat &gt; kubernetes-csr.json &lt;&lt; EOF
{
    &quot;CN&quot;: &quot;kubernetes&quot;,
    &quot;hosts&quot;: [
      &quot;127.0.0.1&quot;,
      &quot;192.168.106.117&quot;,
      &quot;192.168.106.237&quot;,
      &quot;192.168.106.118&quot;,
      &quot;192.168.106.119&quot;,
      &quot;192.168.106.128&quot;,
      &quot;192.168.106.129&quot;,
      &quot;192.168.106.103&quot;,
      &quot;169.169.0.1&quot;,
      &quot;kubernetes&quot;,
      &quot;kubernetes.default&quot;,
      &quot;kubernetes.default.svc&quot;,
      &quot;kubernetes.default.svc.cluster&quot;,
      &quot;kubernetes.default.svc.cluster.local&quot;
    ],
    &quot;key&quot;: {
        &quot;algo&quot;: &quot;rsa&quot;,
        &quot;size&quot;: 2048
    },
    &quot;names&quot;: [
        {
            &quot;C&quot;: &quot;CN&quot;,
            &quot;ST&quot;: &quot;BeiJing&quot;,
            &quot;L&quot;: &quot;BeiJing&quot;,
            &quot;O&quot;: &quot;k8s&quot;,
            &quot;OU&quot;: &quot;System&quot;
        }
    ]
}
EOF

[root@managementa ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
[root@managementa ssl]# ls kubernetes*
kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem
验证证书
[root@managementa ssl]# openssl x509  -noout -text -in  kubernetes.pem
[root@managementa ssl]# cp *.pem ../fk/pki/
[root@managementa ssl]# cd ../fk/pki/
[root@managementa pki]# ls
ca.crt  ca-key.pem  ca.pem  kubernetes-key.pem  kubernetes.pem  server.crt  server.key
[root@managementa pki]# cd ../conf/
[root@managementa conf]# systemctl stop kube-controller-manager
[root@managementa conf]# cat controller-manager 
KUBE_CONTROLLER_MANAGER_ARGS=&quot;--master=http://127.0.0.1:9090 --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --service-account-private-key-file=/root/fk/pki/kubernetes-key.pem --root-ca-file=/root/fk/pki/ca.pem&quot; 
[root@managementa conf]# cat apiserver 
KUBE_API_ARGS=&quot;--enable-aggregator-routing --authorization-mode=RBAC --etcd-servers=http://192.168.106.237:2379 --insecure-bind-address=0.0.0.0 --insecure-port=9090 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --client-ca-file=/root/fk/pki/ca.pem --tls-cert-file=/root/fk/pki/kubernetes.pem --tls-private-key-file=/root/fk/pki/kubernetes-key.pem&quot;
[root@managementa conf]# kubectl get secrets --all-namespaces
NAMESPACE         NAME                  TYPE                                  DATA   AGE
default           default-token-crcnd   kubernetes.io/service-account-token   3      2d
kube-node-lease   default-token-lh2nx   kubernetes.io/service-account-token   3      77m
kube-public       default-token-b76v6   kubernetes.io/service-account-token   3      2d
kube-system       default-token-jv9zg   kubernetes.io/service-account-token   3      2d
[root@managementa conf]# kubectl delete secrets default-token-crcnd
secret &quot;default-token-crcnd&quot; deleted
[root@managementa conf]# kubectl delete secrets default-token-lh2nx -n kube-node-lease
secret &quot;default-token-lh2nx&quot; deleted
[root@managementa conf]# kubectl delete secrets default-token-b76v6 -n kube-public
secret &quot;default-token-b76v6&quot; deleted
[root@managementa conf]#  kubectl delete secrets default-token-jv9zg -n kube-system
secret &quot;default-token-jv9zg&quot; deleted
[root@managementa conf]# kubectl get secrets --all-namespaces
No resources found
[root@managementa conf]# kubectl get serviceaccounts --all-namespaces
NAMESPACE         NAME      SECRETS   AGE
default           default   1         2d
kube-node-lease   default   1         78m
kube-public       default   1         2d
kube-system       default   1         2d
[root@managementa conf]# systemctl stop kube-apiserver
[root@managementa conf]# systemctl start kube-apiserver
[root@managementa conf]# systemctl start kube-controller-manager
[root@managementa fk]# cd kube-metrics-server/
[root@managementa kube-metrics-server]# ls
aggregated-metrics-reader.yaml  auth-delegator.yaml  auth-reader.yaml  metrics-apiservice.yaml  metrics-server-deployment.yaml  metrics-server-service.yaml  resource-reader.yaml
[root@managementa kube-metrics-server]# kubectl apply -f .
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
serviceaccount/metrics-server created
deployment.apps/metrics-server created
service/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
[root@managementa kube-metrics-server]# kubectl get pods --all-namespaces
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
kube-system   metrics-server-6f66574f8d-bx547   1/1     Running   0          9s
[root@managementa kube-metrics-server]# kubectl get pods --all-namespaces
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
kube-system   metrics-server-6f66574f8d-bx547   1/1     Running   0          11s
证书备份，只罗列内容：
[root@managementa pki]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem
[root@managementa pki]# cat ca-key.pem 
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA7FO8JNTypRkTj3eekQhXhikBGEu5ev6TW8KI700MuBaK0RmX
5vibkJ4vuUuvrL0QPoTPnlLs7f8XytMqtaEyQUsrv0R2BvC3Y+HckqNNaqtWCCUL
5KLs2c0FXeTvuX3PIx76Z0Si7Y5NnNusmkUc7zoQRXCwm13WtXTlj6RFImvpxehy
lsxOMaDjaT+U8I/hvvCaTC0rkB1eFyXH7Fw6rv2oui5rm67MBurjHyXjGMHX1WIE
JzF/NH5KKq0tD4bUyfQwLA8M9F9MvSHRvl7nE0moGsAY23r5D778sX2EzMTXHUNk
cO4bE9rqirI2UrBNjNlQHOBZ+Gu7hQMNYJdDPQIDAQABAoIBACfYrn5fUVI4+i1U
c+3sRCWgwEiCbBGq3tm34TLIAP8A/gLnl88f18r4gP9zHXm4nwaLih4dyUkPm8lc
9XSOa1TLAeNL/cKJz8INkQ1Ab4suvGC/LlQsjFbk1KTSNwFFjylSzdGfpwD632c1
OtMAGDLVzWyH5Z8soUkTHqmrfuSgjmYNsGOCM8PK2eF1knxv698mPJY0XU3X5yG2
e1Jl77MT8cJDbO+XuqBvmOWYJ1S55lsTRG58gHHBmhk6il/7i39SgGkHSFavNu5A
lCpkms9id0W5QZ7NethowgMeCTZZent4uMrkCJcm463/kHsGkT3Y9ea+iUNckHOS
DZ5CgEECgYEA9szT1N42r/kACo2NCWE3MEEDp80xTO9YBJs/6v1C/Z0iBbLDDvvW
HejljffUgh9nz0+OG5h9I31UKI6ojRxgIyST6yG2koWJg8EtUGwNqodixoeni07h
Ql04Tcy2QBTeurMafBouafTcKTVEHHp5TPCAzwz59z6jbv3RDfHZBVUCgYEA9SL3
Fy7o8ebs+5oldPLFhtbLFSTu6ELGn9REdG2z2wxOV68ICdjGyjE+njIupw7qS4AX
Smwd+uqApE0AmlTHz+3MJLWnE6m8rjcLG1zFapqDnd//3yS9E0bmQx8ov9IzeI18
QgF5OoXS/vBAlsvF2LTx4NfTHDTaDKzyTmFBxkkCgYBZUFTUszotQro+F23T2Cel
wdF1128g/Xjn6dseylqE92mJkGDAumiJWHBCiU6RbJYf0xWFbRDUWBWtu7rJnlw4
O5OAQyoUKllSogUpFoF3lhkr6Ym7g2dHof6vQQcvd54HCKvr/3mOhLtr+kfU2omt
S1gCFhsb28I/d4FBP6WfJQKBgQDcOa5cQIN8FyceHmy6NQRpz/wgoc6UELGakztw
kcG778FOGuwQ1JQ6v6TuwEyTPt4UOB40eQ8yBYzOjnMVM0dTMOJutFdGXf4pUUAE
NAMTc378zWl1Ee9fKxnggVS9h90/13QjZGmBvwpAiJyuHKFAv8ZxZdO+Cmk+a/0/
lzZdKQKBgCSLHELINvO+uUOXkoUXYYkrYJoH9uUJRFi8Gy5hdOpnMFYGcBiSbU2v
JUACtXBXN1ytmU5nYslKZpCfvzuD0xsfi//z/dDZDYDx8tbEldDJi/svPZu352Yn
rVnz661/xhUj5W3qCnlKE6kyleSStzZsVTTmtSdWXJUAw7XFEGFm
-----END RSA PRIVATE KEY-----
[root@managementa pki]# cat ca.pem
-----BEGIN CERTIFICATE-----
MIIDvjCCAqagAwIBAgIUfSG5ElG6kCDKiUxrkpEPDYyAa0cwDQYJKoZIhvcNAQEL
BQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl
aUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr
dWJlcm5ldGVzMB4XDTE5MTExMzA3MTkwMFoXDTI0MTExMTA3MTkwMFowZTELMAkG
A1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0JlaUppbmcxDDAK
BgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwprdWJlcm5ldGVz
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7FO8JNTypRkTj3eekQhX
hikBGEu5ev6TW8KI700MuBaK0RmX5vibkJ4vuUuvrL0QPoTPnlLs7f8XytMqtaEy
QUsrv0R2BvC3Y+HckqNNaqtWCCUL5KLs2c0FXeTvuX3PIx76Z0Si7Y5NnNusmkUc
7zoQRXCwm13WtXTlj6RFImvpxehylsxOMaDjaT+U8I/hvvCaTC0rkB1eFyXH7Fw6
rv2oui5rm67MBurjHyXjGMHX1WIEJzF/NH5KKq0tD4bUyfQwLA8M9F9MvSHRvl7n
E0moGsAY23r5D778sX2EzMTXHUNkcO4bE9rqirI2UrBNjNlQHOBZ+Gu7hQMNYJdD
PQIDAQABo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAd
BgNVHQ4EFgQUwDWSzTl7CZ7y4bMAGSeLLrfUmzYwHwYDVR0jBBgwFoAUwDWSzTl7
CZ7y4bMAGSeLLrfUmzYwDQYJKoZIhvcNAQELBQADggEBAHeAY4J5N+s4CKO1eR2/
e7MyPgbqDQ/pGB7LImf9cgfxd/Ufgr4RODXXDb+cHOYr+whzMfFWszzACqFTvjBj
0ZAUIAVOpBvBhNYFlrbEyupRJewb9cxAhXSLLGPr3EyzNtOOGdV6c6wih99sng+Z
I0SjwutkUpap5QfUo+/Up3QmpPixqUPa99U6Pi2u9Kr2qOk8pVv2uAHpF3Bu4Roi
jp04jD0FKLDUGuwf9QpMVW4BGvxmwqIXzTnY65ksz4ckdKamB3pMXxJ6iCRArnOn
anAbX024gNoTPcAbuP0TSNJjo4p1vg3agNQBIU88+fPQUzx+9tOkTiBtziwyhzcu
A7g=
-----END CERTIFICATE-----
[root@managementa pki]# cat ca.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICqjCCAZICAQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAO
BgNVBAcTB0JlaUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMw
EQYDVQQDEwprdWJlcm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA7FO8JNTypRkTj3eekQhXhikBGEu5ev6TW8KI700MuBaK0RmX5vibkJ4vuUuv
rL0QPoTPnlLs7f8XytMqtaEyQUsrv0R2BvC3Y+HckqNNaqtWCCUL5KLs2c0FXeTv
uX3PIx76Z0Si7Y5NnNusmkUc7zoQRXCwm13WtXTlj6RFImvpxehylsxOMaDjaT+U
8I/hvvCaTC0rkB1eFyXH7Fw6rv2oui5rm67MBurjHyXjGMHX1WIEJzF/NH5KKq0t
D4bUyfQwLA8M9F9MvSHRvl7nE0moGsAY23r5D778sX2EzMTXHUNkcO4bE9rqirI2
UrBNjNlQHOBZ+Gu7hQMNYJdDPQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAHJQ
QJlDBiXnuZ7H/yTBSRu6LNNP1uuTriO514lS3DBt8NydHYz8B8XMufgzdDdHWWz9
sJXL5iw4MYOFXc9QhCBDLxFqNdCduMvn+cdVkAAAA1uk0G7R4VADV+w1ikB5qCFV
EgjCQsBajITkfqLDxarwZWc/nlRqsiXulWVRjKTmaXGULg0PSslZECXzxb19tvp4
qPEBlqZDXnfVNB0KSL5lJvbiyqeJnIdveOy+qer5aYvjtPbpk9quE2ufTuQCsBGx
FyZasR7Dk6s4dpW3cjRqsTHryy2xeZn3fM4uGDzriyHySW2hOAErMW3dHngndM7E
SqXAYR3oJKSjnGskp0E=
-----END CERTIFICATE REQUEST-----
[root@managementa pki]# cat ca-csr.json
{
  &quot;CN&quot;: &quot;kubernetes&quot;,
  &quot;key&quot;: {
    &quot;algo&quot;: &quot;rsa&quot;,
    &quot;size&quot;: 2048
  },
  &quot;names&quot;: [
    {
      &quot;C&quot;: &quot;CN&quot;,
      &quot;ST&quot;: &quot;BeiJing&quot;,
      &quot;L&quot;: &quot;BeiJing&quot;,
      &quot;O&quot;: &quot;k8s&quot;,
      &quot;OU&quot;: &quot;System&quot;
    }
  ]
}
[root@managementa pki]# cat ca-config.json
{
  &quot;signing&quot;: {
    &quot;default&quot;: {
      &quot;expiry&quot;: &quot;87600h&quot;
    },
    &quot;profiles&quot;: {
      &quot;kubernetes&quot;: {
        &quot;usages&quot;: [
            &quot;signing&quot;,
            &quot;key encipherment&quot;,
            &quot;server auth&quot;,
            &quot;client auth&quot;
        ],
        &quot;expiry&quot;: &quot;87600h&quot;
      }
    }
  }
}
[root@managementa pki]# cat kubernetes-csr.json
{
    &quot;CN&quot;: &quot;kubernetes&quot;,
    &quot;hosts&quot;: [
      &quot;127.0.0.1&quot;,
      &quot;192.168.106.117&quot;,
      &quot;192.168.106.237&quot;,
      &quot;192.168.106.118&quot;,
      &quot;192.168.106.119&quot;,
      &quot;192.168.106.128&quot;,
      &quot;192.168.106.129&quot;,
      &quot;192.168.106.103&quot;,
      &quot;169.169.0.1&quot;,
      &quot;kubernetes&quot;,
      &quot;kubernetes.default&quot;,
      &quot;kubernetes.default.svc&quot;,
      &quot;kubernetes.default.svc.cluster&quot;,
      &quot;kubernetes.default.svc.cluster.local&quot;
    ],
    &quot;key&quot;: {
        &quot;algo&quot;: &quot;rsa&quot;,
        &quot;size&quot;: 2048
    },
    &quot;names&quot;: [
        {
            &quot;C&quot;: &quot;CN&quot;,
            &quot;ST&quot;: &quot;BeiJing&quot;,
            &quot;L&quot;: &quot;BeiJing&quot;,
            &quot;O&quot;: &quot;k8s&quot;,
            &quot;OU&quot;: &quot;System&quot;
        }
    ]
}
[root@managementa pki]# cat kubernetes.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIDgTCCAmkCAQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAO
BgNVBAcTB0JlaUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMw
EQYDVQQDEwprdWJlcm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA2Yhv0Je+Yxs9rqGkIBd3Jy1loq9bnHMgA8nVpu//QVR4n8Fqq3Lvt3/XnJg3
6u/l0UufVQD/hd+MWKL/bqnJMYb5YGBZCd1P5VOE3YyKmIgiea79y1XUjl5Bvn8i
5ReQINT3RIrXqdw0Qm/bSSqvopTC6VPSN8Ax6eI0Lnr1sLdTH6zA1UsUtKCHmM0W
h92PF158dihjy/YrtjMFe91P9dOJocbwwARzxJlRO21OSJC4P/zkpDWBtd8Oxjs5
UIkjXI6QDxx/cStGP2lJAm39Wgu2gg835gglhD8oeVnwfbRl52BBdKmH2UL/Nb/o
VkUVHK1W6bosFqE3SLDHmhPc9QIDAQABoIHWMIHTBgkqhkiG9w0BCQ4xgcUwgcIw
gb8GA1UdEQSBtzCBtIIKa3ViZXJuZXRlc4ISa3ViZXJuZXRlcy5kZWZhdWx0ghZr
dWJlcm5ldGVzLmRlZmF1bHQuc3Zjgh5rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNs
dXN0ZXKCJGt1YmVybmV0ZXMuZGVmYXVsdC5zdmMuY2x1c3Rlci5sb2NhbIcEfwAA
AYcEwKhqdYcEwKhq7YcEwKhqdocEwKhqd4cEwKhqgIcEwKhqgYcEwKhqZ4cEqakA
ATANBgkqhkiG9w0BAQsFAAOCAQEAUT/KK1VXLRBBy4tA6jIGb5T8m2Qmlhsh8LMI
0KjwplN0BR0t7lHvd7BHokR/dBgEZRTX3BowxWUgmZCH16q9BFwv1MSEs/wcCn6A
/TCPfA5skayhkL2FPZSQNoxHmGdjimYMGMcmdh6rrXBwzQZdfLHiIzmC1Q0XWIxz
Z5v6g2nV52NM9Ho3AMD43t1sl2BXya2CkrpjzKm3y7uAkMYzukxnXEDHuXcduROh
ngJX7dbWRZhd3OmdeuZRu+JbDMlJcY5kZHrErO5DaYRpdc2lcmfOJALTm40X5W/1
w3j63RnKtNsboBTSeqjyKYfbryBJQ5LYTu83LWoDckVWQa66YA==
-----END CERTIFICATE REQUEST-----
[root@managementa pki]# cat  kubernetes-key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA2Yhv0Je+Yxs9rqGkIBd3Jy1loq9bnHMgA8nVpu//QVR4n8Fq
q3Lvt3/XnJg36u/l0UufVQD/hd+MWKL/bqnJMYb5YGBZCd1P5VOE3YyKmIgiea79
y1XUjl5Bvn8i5ReQINT3RIrXqdw0Qm/bSSqvopTC6VPSN8Ax6eI0Lnr1sLdTH6zA
1UsUtKCHmM0Wh92PF158dihjy/YrtjMFe91P9dOJocbwwARzxJlRO21OSJC4P/zk
pDWBtd8Oxjs5UIkjXI6QDxx/cStGP2lJAm39Wgu2gg835gglhD8oeVnwfbRl52BB
dKmH2UL/Nb/oVkUVHK1W6bosFqE3SLDHmhPc9QIDAQABAoIBAQCpNvzj4mZzaald
wteNLzO9Ag9hsc8tsFBjIgpUxbRl+XOrsiVsIQhgUc5DPhWhZ+P6Hz1ePlyGoxLl
kEXqq6CaKkiqs8gPaFzSI1njjYPyi1NmHL3IAohKBwBVU0ittNqk74U5iFejBmyQ
kbqe+9mMOvQz1MReId+x9Ahrb7LXNxP9OtbuM5EUgMTFlsfrrgtNNJN0lg/BbmJn
mmPBe3MrEBr1EW5I/ZfWXdQcjqILxZEJZ9TfnB77Fj2gmNrIFxBKPNvn/Kl0ek0f
xFHfIU934aLCg/Ywmts+9BcbtKtBnHHOd6gnCB5dKgwl8/qKJfafCPhcraij8GKr
WmB3tXCxAoGBAP6G0BIJW91OY7tAgfRwuplYzFfV+Tx0LTCz5Gmh3DawWSoex6Hr
0gVo8Pm9wcEOSwXBUMuuMRxgFGWFZEazbDM4IuidVLcJIR2czmrU3gf0t+D1mkOf
N5+lMMOHE35cFcO6hHFnf/n7kkAN0RHxiO9+aVOlPe1diWdho0kkLzYjAoGBANrK
zW+9j2iHtks9BL4/wuRp6F7KMndZZr07z2fJ2+AiIThMHpsLVaNi1xH10AkRVpsZ
c/cEmEc/86I1dVTUvis/7tjaPxaYwA1jQ/yC1TP/tI57h8/MCrGR7ZplpuzymV+x
7E98TGq/qMky+tOXP9580vMwsK8JoktLRzPuCjYHAoGBALfY1O5SSELAXpVg8P2J
d59QXrmLWy3plMK7Dd+nBJOUKbOc7AHvfpJdzMH36L3z/wi3LA8TUXH3jIQQJ/BR
pXQRtlVjX0+ejob/PrI38/C3OSKLBNSXauwru99f8BqzlRz92rC3W99LccZGtJ9L
Yefr3VSH5QVRLPC5u+IW+usVAoGBAMWL2SOsDyD9cB3M0UyJu4mLCnETta9HPFld
+G2ot+tORZpUOEobWM51/uRLgvO9AOp3d9ov/uJOHsd15yOaFr5sMlb/73iSoM01
tHv5EVGq7ja72KtJetpLfTIr2CUXAl6CAnDeNQ0pUdegPRLw/I0BPWKwssbINw4u
wPJlWjjfAoGAVaDYwBeDHLbrzHYEJ8FejDT8h6UgeOL7sw3ua+OQjj5gM+/UlQZh
fpSIL7h93Zc3f7LBcDxo60THWDotm6TfLqu1RMco49FpxN6/3naqDjwL9t73b2uz
XdyCq5lI6PHQzy7PlVLP/TWzZW1YT4DpkRAc7S1zyGQxImW1UzZ4oO4=
-----END RSA PRIVATE KEY-----
[root@managementa pki]# cat  kubernetes.pem
-----BEGIN CERTIFICATE-----
MIIEnTCCA4WgAwIBAgIUXkAeoDoFReJbakmRKjvWJji/W+0wDQYJKoZIhvcNAQEL
BQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl
aUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr
dWJlcm5ldGVzMB4XDTE5MTExMzA3MjUwMFoXDTI5MTExMDA3MjUwMFowZTELMAkG
A1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0JlaUppbmcxDDAK
BgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwprdWJlcm5ldGVz
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Yhv0Je+Yxs9rqGkIBd3
Jy1loq9bnHMgA8nVpu//QVR4n8Fqq3Lvt3/XnJg36u/l0UufVQD/hd+MWKL/bqnJ
MYb5YGBZCd1P5VOE3YyKmIgiea79y1XUjl5Bvn8i5ReQINT3RIrXqdw0Qm/bSSqv
opTC6VPSN8Ax6eI0Lnr1sLdTH6zA1UsUtKCHmM0Wh92PF158dihjy/YrtjMFe91P
9dOJocbwwARzxJlRO21OSJC4P/zkpDWBtd8Oxjs5UIkjXI6QDxx/cStGP2lJAm39
Wgu2gg835gglhD8oeVnwfbRl52BBdKmH2UL/Nb/oVkUVHK1W6bosFqE3SLDHmhPc
9QIDAQABo4IBQzCCAT8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF
BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTr2g9b5ihjJg1q
5D8XCjX2yE9I5jAfBgNVHSMEGDAWgBTANZLNOXsJnvLhswAZJ4sut9SbNjCBvwYD
VR0RBIG3MIG0ggprdWJlcm5ldGVzghJrdWJlcm5ldGVzLmRlZmF1bHSCFmt1YmVy
bmV0ZXMuZGVmYXVsdC5zdmOCHmt1YmVybmV0ZXMuZGVmYXVsdC5zdmMuY2x1c3Rl
coIka3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FshwR/AAABhwTA
qGp1hwTAqGrthwTAqGp2hwTAqGp3hwTAqGqAhwTAqGqBhwTAqGpnhwSpqQABMA0G
CSqGSIb3DQEBCwUAA4IBAQBibcKxXIvEu1RurTxjaaadTkO5lWU+6L2zar4KepdV
XQXiW+q1HvwVJl3ZM86I8xF8mp6nkH6SbUHx/tY8VT0WI7jC1wohUleli1AtnljR
BU2Ngq7v6kw/aH4CuVYryVU4YmLTGAKX8ZCt36/0uZKDq94q3E8EijUJXSi8Ek/O
CCldw/bJ5tCCo1lcfJiioRikbcFXo4zzt1hiILADxmqfjMv/75gTmyqygb5zkBfd
4YQG+XBkTZRvGKPEQjQzlLe8Pt0c22EjAoD4HamF95+eblEiTlmavCN4uHt3bSb9
ud4AtKd8+HhpC5m5fvvTrxgsCDDc671uDaXbiyb09X2w
-----END CERTIFICATE-----
[root@managementa pki]# 
</code></pre><h3 id="k8s-dns安装">k8s DNS安装</h3>
<pre><code>k8s集群部署完后第一件事就是要配置DNS服务，目前可选的方案有skydns, kube-dns, coredns
[root@managementa fk]# pwd
/root/fk
[root@managementa fk]# mkdir kube-dns
[root@managementa fk]# cd kube-dns/
[root@managementa kube-dns]# wget -O kube-dns.yaml https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.16/cluster/addons/dns/kube-dns/kube-dns.yaml.base
[root@managementa kube-dns]# docker pull netonline/k8s-dns-dnsmasq-nanny-amd64:1.14.8
[root@managementa kube-dns]# docker pull netonline/k8s-dns-kube-dns-amd64:1.14.8
[root@managementa kube-dns]# docker pull netonline/k8s-dns-sidecar-amd64:1.14.8
[root@managementa kube-dns]# docker tag netonline/k8s-dns-dnsmasq-nanny-amd64:1.14.8 192.168.106.117/library/k8s-dns-dnsmasq-nanny-amd64:1.14.8
[root@managementa kube-dns]# docker tag netonline/k8s-dns-kube-dns-amd64:1.14.8 192.168.106.117/library/k8s-dns-kube-dns-amd64:1.14.8
[root@managementa kube-dns]# docker tag netonline/k8s-dns-sidecar-amd64:1.14.8  192.168.106.117/library/k8s-dns-sidecar-amd64:1.14.8
[root@managementa kube-dns]# docker push 192.168.106.117/library/k8s-dns-dnsmasq-nanny-amd64:1.14.8
[root@managementa kube-dns]# docker push 192.168.106.117/library/k8s-dns-kube-dns-amd64:1.14.8
[root@managementa kube-dns]# docker push 192.168.106.117/library/k8s-dns-sidecar-amd64:1.14.8 

[root@managementa kube-dns]# docker rmi  netonline/k8s-dns-dnsmasq-nanny-amd64:1.14.8
[root@managementa kube-dns]# docker rmi netonline/k8s-dns-kube-dns-amd64:1.14.8
[root@managementa kube-dns]#  docker rmi netonline/k8s-dns-sidecar-amd64:1.14.8
[root@managementa kube-dns]# 
**修改yaml配置**
[root@managementa kube-dns]# cat kube-dns.yaml 
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml
# in sync with this file.

# __MACHINE_GENERATED_WARNING__

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: &quot;true&quot;
    addonmanager.kubernetes.io/mode: Reconcile
    kubernetes.io/name: &quot;KubeDNS&quot;
spec:
  selector:
    k8s-app: kube-dns
  ### 修改的
  clusterIP: 169.169.169.169
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: &quot;true&quot;
    addonmanager.kubernetes.io/mode: Reconcile
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: &quot;true&quot;
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  # replicas: not specified here:
  # 1. In order to make Addon Manager do not reconcile this replicas parameter.
  # 2. Default is 1.
  # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 0
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
        prometheus.io/port: &quot;10054&quot;
        prometheus.io/scrape: &quot;true&quot;
    spec:
      priorityClassName: system-cluster-critical
      securityContext:
        supplementalGroups: [ 65534 ]
        fsGroup: 65534
      tolerations:
      - key: &quot;CriticalAddonsOnly&quot;
        operator: &quot;Exists&quot;
      volumes:
      - name: kube-dns-config
        configMap:
          name: kube-dns
          optional: true
      containers:
      - name: kubedns
        image: 192.168.106.117/library/k8s-dns-kube-dns-amd64:1.14.8
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # &quot;burstable&quot; category so the kubelet doesn't backoff from restarting it.
          limits:
            ###修改的
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthcheck/kubedns
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        - --domain=cluster.local.
        - --dns-port=10053
        - --config-dir=/kube-dns-config
        - --v=2
        env:
        - name: PROMETHEUS_PORT
          value: &quot;10055&quot;
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
        - containerPort: 10055
          name: metrics
          protocol: TCP
        volumeMounts:
        - name: kube-dns-config
          mountPath: /kube-dns-config
      - name: dnsmasq
        image: 192.168.106.117/library/k8s-dns-dnsmasq-nanny-amd64:1.14.8
        livenessProbe:
          httpGet:
            path: /healthcheck/dnsmasq
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - -v=2
        - -logtostderr
        - -configDir=/etc/k8s/dns/dnsmasq-nanny
        - -restartDnsmasq=true
        - --
        - -k
        - --cache-size=1000
        - --no-negcache
        - --dns-loop-detect
        - --log-facility=-
        - --server=/cluster.local./127.0.0.1#10053
        - --server=/in-addr.arpa/127.0.0.1#10053
        - --server=/ip6.arpa/127.0.0.1#10053
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
        resources:
          requests:
            cpu: 150m
            memory: 20Mi
        volumeMounts:
        - name: kube-dns-config
          mountPath: /etc/k8s/dns/dnsmasq-nanny
      - name: sidecar
        image: 192.168.106.117/library/k8s-dns-sidecar-amd64:1.14.8
        livenessProbe:
          httpGet:
            path: /metrics
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --v=2
        - --logtostderr
        - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local.,5,SRV
        - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local.,5,SRV
        ports:
        - containerPort: 10054
          name: metrics
          protocol: TCP
        resources:
          requests:
            memory: 20Mi
            cpu: 10m
      dnsPolicy: Default  # Don't use cluster DNS.
      serviceAccountName: kube-dns
      
[root@managementa kube-dns]# kubectl create -f kube-dns.yaml
[root@managementa kube-dns]# kubectl get pod -n kube-system -o wide
[root@managementa kube-dns]# kubectl get service -n kube-system -o wide
[root@managementa kube-dns]# kubectl get deployment -n kube-system -o wide

验证
 如果我们此前已经有了部署了许多pod和服务，并且在Kubelet 启动配置文件加入了 --cluster-dns=169.169.169.169 --cluster-domain=cluster.local 
 
 dns验证
 root@managementa:~/fk/dns-test[root@managementa dns-test]# cat bsy-box.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: busybox
    role: master
  name: busybox
spec:
  containers:
  - name: busybox
    image: docker.io/busybox:latest
    command:
    - sleep
    - &quot;3600&quot;
</code></pre><h3 id="dashboard-安装">Dashboard 安装</h3>
<pre><code>安装v1.10.1有很多404错误，找不到heapster服务等错误，heapster已经被metrics server取代，可能是版本问题，安装最新版本。
GITHUB: https://github.com/kubernetes/dashboard
RELEASE: https://github.com/kubernetes/dashboard/releases

[root@managementa kube-dashboard]# wget  https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta5/aio/deploy/recommended.yaml 

[root@managementa kube-dashboard]# cat recommended.yaml 
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Namespace
metadata:
  name: kubernetes-dashboard

---

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 31001
  selector:
    k8s-app: kubernetes-dashboard

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kubernetes-dashboard
type: Opaque

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-csrf
  namespace: kubernetes-dashboard
type: Opaque
data:
  csrf: &quot;&quot;

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-key-holder
  namespace: kubernetes-dashboard
type: Opaque

---

kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-settings
  namespace: kubernetes-dashboard

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  - apiGroups: [&quot;&quot;]
    resources: [&quot;secrets&quot;]
    resourceNames: [&quot;kubernetes-dashboard-key-holder&quot;, &quot;kubernetes-dashboard-certs&quot;, &quot;kubernetes-dashboard-csrf&quot;]
    verbs: [&quot;get&quot;, &quot;update&quot;, &quot;delete&quot;]
    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  - apiGroups: [&quot;&quot;]
    resources: [&quot;configmaps&quot;]
    resourceNames: [&quot;kubernetes-dashboard-settings&quot;]
    verbs: [&quot;get&quot;, &quot;update&quot;]
    # Allow Dashboard to get metrics.
  - apiGroups: [&quot;&quot;]
    resources: [&quot;services&quot;]
    resourceNames: [&quot;heapster&quot;, &quot;dashboard-metrics-scraper&quot;]
    verbs: [&quot;proxy&quot;]
  - apiGroups: [&quot;&quot;]
    resources: [&quot;services/proxy&quot;]
    resourceNames: [&quot;heapster&quot;, &quot;http:heapster:&quot;, &quot;https:heapster:&quot;, &quot;dashboard-metrics-scraper&quot;, &quot;http:dashboard-metrics-scraper&quot;]
    verbs: [&quot;get&quot;]

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: [&quot;metrics.k8s.io&quot;]
    resources: [&quot;pods&quot;, &quot;nodes&quot;]
    verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
        - name: kubernetes-dashboard
          image: 192.168.106.117/library/kubernetesui/dashboard:v2.0.0-beta5
          imagePullPolicy: Always
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            # Uncomment the following line to manually specify Kubernetes API server Host
            # If not specified, Dashboard will attempt to auto discover the API server and connect
            # to it. Uncomment only if the default does not work.
            # - --apiserver-host=http://my-address:port
          volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
              # Create on-disk volume to store exec logs
            - mountPath: /tmp
              name: tmp-volume
          livenessProbe:
            httpGet:
              scheme: HTTPS
              path: /
              port: 8443
            initialDelaySeconds: 30
            timeoutSeconds: 30
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      volumes:
        - name: kubernetes-dashboard-certs
          secret:
            secretName: kubernetes-dashboard-certs
        - name: tmp-volume
          emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        &quot;beta.kubernetes.io/os&quot;: linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 8000
      targetPort: 8000
  selector:
    k8s-app: dashboard-metrics-scraper

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: dashboard-metrics-scraper
  template:
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
    spec:
      containers:
        - name: dashboard-metrics-scraper
          image: 192.168.106.117/library/metrics-scraper:v1.0.1
          ports:
            - containerPort: 8000
              protocol: TCP
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /
              port: 8000
            initialDelaySeconds: 30
            timeoutSeconds: 30
          volumeMounts:
          - mountPath: /tmp
            name: tmp-volume
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        &quot;beta.kubernetes.io/os&quot;: linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      volumes:
        - name: tmp-volume
          emptyDir: {}
          
          
          

本地下载image
[root@managementa kube-dashboard]# docker pull kubernetesui/dashboard:v2.0.0-beta5
[root@managementa kube-dashboard]# docker tag kubernetesui/dashboard:v2.0.0-beta5 192.168.106.117/library/kubernetesui/dashboard:v2.0.0-beta5
[root@managementa kube-dashboard]# docker push 192.168.106.117/library/kubernetesui/dashboard:v2.0.0-beta5
[root@managementa kube-dashboard]# docker rmi kubernetesui/dashboard:v2.0.0-beta5
修改image为:192.168.106.117/library/kubernetesui/dashboard:v2.0.0-beta5

[root@managementa kube-dashboard]# docker pull kubernetesui/metrics-scraper:v1.0.1
[root@managementa kube-dashboard]# docker tag kubernetesui/metrics-scraper:v1.0.1 192.168.106.117/library/metrics-scraper:v1.0.1
[root@managementa kube-dashboard]# docker push 192.168.106.117/library/metrics-scraper:v1.0.1
[root@managementa kube-dashboard]# docker rmi kubernetesui/metrics-scraper:v1.0.1
修改image为:192.168.106.117/library/metrics-scraper:v1.0.1

修改服务为NodePort，暴露服务

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 31001
  selector:
    k8s-app: kubernetes-dashboard

[root@managementa kube-dashboard]# kubectl create -f recommended.yaml 
namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created




**创建dashboard管理员用户**

[root@managementa kube-dashboard]# cat dashboard-admin.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: dashboard-admin
  namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dashboard-admin-bind-cluster-role
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: dashboard-admin
  namespace: kubernetes-dashboard
[root@managementa kube-dashboard]# kubectl create -f dashboard-admin.yaml 
[root@managementa kube-dashboard]# kubectl get secrets --all-namespaces
NAMESPACE              NAME                                       TYPE                                  DATA   AGE
default                default-token-499vm                        kubernetes.io/service-account-token   3      18h
ingress-nginx          default-token-wqpw4                        kubernetes.io/service-account-token   3      11h
ingress-nginx          nginx-ingress-serviceaccount-token-xjvth   kubernetes.io/service-account-token   3      11h
kube-node-lease        default-token-brjgg                        kubernetes.io/service-account-token   3      18h
kube-public            default-token-944rr                        kubernetes.io/service-account-token   3      18h
kube-system            default-token-d6z59                        kubernetes.io/service-account-token   3      18h
kube-system            kube-dns-token-xh646                       kubernetes.io/service-account-token   3      18h
kube-system            kubernetes-dashboard-key-holder            Opaque                                2      18h
kube-system            metrics-server-token-sxsg6                 kubernetes.io/service-account-token   3      10h
kubernetes-dashboard   dashboard-admin-token-pk4vg                kubernetes.io/service-account-token   3      12s
kubernetes-dashboard   default-token-76s42                        kubernetes.io/service-account-token   3      29m
kubernetes-dashboard   kubernetes-dashboard-certs                 Opaque                                0      29m
kubernetes-dashboard   kubernetes-dashboard-csrf                  Opaque                                1      29m
kubernetes-dashboard   kubernetes-dashboard-key-holder            Opaque                                2      29m
kubernetes-dashboard   kubernetes-dashboard-token-b5r9b           kubernetes.io/service-account-token   3      29m

[root@managementa kube-dashboard]# kubectl describe secrets dashboard-admin-token-pk4vg -n kubernetes-dashboard 
Name:         dashboard-admin-token-pk4vg
Namespace:    kubernetes-dashboard
Labels:       &lt;none&gt;
Annotations:  kubernetes.io/service-account.name: dashboard-admin
              kubernetes.io/service-account.uid: adf25208-0634-4395-9e20-ad1dc5721cf3

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1359 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IlhZLVNXNFhUM3ZWeW56M1hWYk5GRm9zZU9HZ1dBbk5ZVzM5VUhmbURaU1UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tcGs0dmciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYWRmMjUyMDgtMDYzNC00Mzk1LTllMjAtYWQxZGM1NzIxY2YzIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZC1hZG1pbiJ9.QKKFKcD1sPxnoTv24bd7CQKXm1QNwfHiRGOhs-1ZluI4xDzsZsDg3ju-9wYFK5dQqtVnhQAqhovisUFt0tU6QHA0bcqJf4wcP5oyHUH2m4ZiKua5WjViFpaOTTaS8g_3q0yzoHBeTecc7LiBRu9pi38SHonZpz6pePKfBSqJPslj111OSwYcTKR5iLx5dsVkil80y04SNWlxP-mQvrBACIrAgxYAeGQMHvyoZ88ScQoMJR_jSUkXsg-SG9JJhY4JFyu4o_0oETRR0xP7FfytYAagUkL3ffXmaBzf1h0IkMrSYUbi7w_mcWMDjJhyavNI2kO1w9AQB6eXjL2BR2bAUw
</code></pre><h3 id="metrics-server安装k8s从17版本开始引入metrics-server替代heapster">metrics server安装(K8S从1.7版本开始引入metrics server替代heapster)</h3>
<pre><code>apiserver开启如下参数
--requestheader-client-ca-file=
--proxy-client-cert-file=
--proxy-client-key-file=
--requestheader-allowed-names=
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--enable-aggregator-routing=true

==============================================================================================
我的环境如下配置
--requestheader-client-ca-file=/root/fk/pki/ca.pem --proxy-client-cert-file=/root/fk/pki/kubernetes.pem --proxy-client-key-file=/root/fk/pki/kubernetes-key.pem
--requestheader-allowed-names=
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--enable-aggregator-routing=true
===============================================================================================

下载地址https://github.com/kubernetes-incubator/metrics-server/
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/aggregated-metrics-reader.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/auth-delegator.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/auth-reader.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/metrics-apiservice.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/metrics-server-deployment.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/metrics-server-service.yaml
[root@managementa kube-metrics-server]# wget https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/master/deploy/1.8%2B/resource-reader.yaml
[root@managementa kube-metrics-server]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
v0.3.6: Pulling from google_containers/metrics-server-amd64
e8d8785a314f: Pull complete 
b2f4b24bed0d: Pull complete 
Digest: sha256:c9c4e95068b51d6b33a9dccc61875df07dc650abbf4ac1a19d58b4628f89288b
Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
[root@managementa kube-metrics-server]# docker tag   registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 192.168.106.117/library/metrics-server-amd64:v0.3.6
[root@managementa kube-metrics-server]# docker push 192.168.106.117/library/metrics-server-amd64:v0.3.6
The push refers to repository [192.168.106.117/library/metrics-server-amd64]
7bf3709d22bb: Pushed 
932da5156413: Pushed 
v0.3.6: digest: sha256:c9c4e95068b51d6b33a9dccc61875df07dc650abbf4ac1a19d58b4628f89288b size: 738
[root@managementa kube-metrics-server]# docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
Untagged: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
Untagged: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64@sha256:c9c4e95068b51d6b33a9dccc61875df07dc650abbf4ac1a19d58b4628f89288b
[root@managementa kube-metrics-server]# 
修改metrics-server-deployment.yaml，添加command和修改imagePullPolicy
[root@managementa kube-metrics-server]# vi metrics-server-deployment.yaml 
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      containers:
      - name: metrics-server
        image: 192.168.106.117/library/metrics-server-amd64:v0.3.6
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
        ports:
        - name: main-port
          containerPort: 4443
          protocol: TCP
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        imagePullPolicy: IfNotPresent
        command:
        - /metrics-server
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
          
下面的文件是不用修改的，只罗列内容
[root@managementa kube-metrics-server]# cat aggregated-metrics-reader.yaml 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:aggregated-metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-edit: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-admin: &quot;true&quot;
rules:
- apiGroups: [&quot;metrics.k8s.io&quot;]
  resources: [&quot;pods&quot;, &quot;nodes&quot;]
  verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]
  
[root@managementa kube-metrics-server]# cat auth-reader.yaml 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
[root@managementa kube-metrics-server]# cat resource-reader.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
rules:
- apiGroups:
  - &quot;&quot;
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
[root@managementa kube-metrics-server]# cat auth-delegator.yaml 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
[root@managementa kube-metrics-server]# cat metrics-apiservice.yaml
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
spec:
  service:
    name: metrics-server
    namespace: kube-system
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100
[root@managementa kube-metrics-server]# cat metrics-server-service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/name: &quot;Metrics-server&quot;
    kubernetes.io/cluster-service: &quot;true&quot;
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: main-port
[root@managementa kube-metrics-server]# 
[root@managementa kube-metrics-server]# kubectl apply -f .



apiserver 加入参数 ： --enable-aggregator-routing ==》将聚合器请求路由到端点IP而不是集群IP。

root@managementa:~/fk/kube-metrics-server[root@managementa kube-metrics-server]# kubectl top nodes
NAME              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
192.168.106.103   26m          0%     1397Mi          18%       
192.168.106.118   639m         15%    3068Mi          83%       
192.168.106.119   64m          1%     2551Mi          69%       
192.168.106.128   27m          0%     1403Mi          38%       
192.168.106.129   21m          0%     1442Mi          39%    
</code></pre><h3 id="ingress安装">Ingress安装</h3>
<pre><code>**apiserver配置**
--authorization-mode=RBAC

在https://github.com/kubernetes/ingress-nginx.git下的deploy/static目录下的mandatory.yaml文件，现在的网址是：https://github.com/kubernetes/ingress-nginx/blob/master/deploy/static/mandatory.yaml 。



在互联网上下载image
[root@managementa ~]# docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
[root@yth-test ~]# docker save -o nginx-ingress-controller quay.io/kubernetes-ingress-controller/nginx-ingress-controller

内网导入

[root@managementa ~]# docker load -i nginx-ingress-controller
[root@managementa ~]# docker tag quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1 192.168.106.117/library/nginx-ingress-controller:0.26.1 
[root@managementa ~]# docker push  192.168.106.117/library/nginx-ingress-controller:0.26.1
The push refers to repository [192.168.106.117/library/nginx-ingress-controller]
30b6afc750c8: Pushed 
177e60f33aba: Pushed 
2cea43e70d3a: Pushed 
c51e4b7a59da: Pushed 
82c8c9d646ea: Pushed 
617b955bc962: Pushed 
4a812d06ca7b: Pushed 
3f8f5020e91a: Pushed 
fff9425704ad: Pushed 
23e1268cd811: Pushed 
e6f1810f12b9: Pushed 
69f5d91486f1: Pushed 
0.26.1: digest: sha256:5da1b2e84ecbdb27facbea84bc6ddc9d50145d824963230735b47828891cba7b size: 2839



修改image为192.168.106.117/library/nginx-ingress-controller:0.26.1
**和一些其他参数的修改**，经过修改后的文件内容是：

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - &quot;&quot;
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - &quot;&quot;
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - &quot;&quot;
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - &quot;&quot;
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - &quot;extensions&quot;
      - &quot;networking.k8s.io&quot;
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - &quot;extensions&quot;
      - &quot;networking.k8s.io&quot;
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - &quot;&quot;
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - &quot;&quot;
    resources:
      - configmaps
    resourceNames:
      # Defaults to &quot;&lt;election-id&gt;-&lt;ingress-class&gt;&quot;
      # Here: &quot;&lt;ingress-controller-leader&gt;-&lt;nginx&gt;&quot;
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - &quot;ingress-controller-leader-nginx&quot;
    verbs:
      - get
      - update
  - apiGroups:
      - &quot;&quot;
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - &quot;&quot;
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: &quot;10254&quot;
        prometheus.io/scrape: &quot;true&quot;
    spec:
      # wait up to five minutes for the drain of connections
      #新加
      hostNetwork: true
      #如果已安装kube-dns那么优先使用k8s的dns，重点
      dnsPolicy: ClusterFirstWithHostNet
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image:  192.168.106.117/library/nginx-ingress-controller:0.26.1
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
            #新加apiserver
            - --apiserver-host=http://192.168.106.117:9090
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -&gt; 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            #新加变量
            - name: KUBERNETES_MASTER
              value: http://192.168.106.117:9090
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

[root@managementa workdir]# kubectl create -f mandaroty.yaml 
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created

</code></pre><h4 id="错误解决">错误解决</h4>
<ul>
<li>Nov  8 12:49:33 managementa kube-controller-manager: E1108 12:49:33.842331   30295 replica_set.go:450] Sync &ldquo;ingress-nginx/nginx-ingress-controller-579bdfc57f&rdquo; failed with pods &ldquo;nginx-ingress-controller-579bdfc57f-x9v54&rdquo; is forbidden: SecurityContext.RunAsUser is forbidden</li>
</ul>
<pre><code>[root@managementa conf]# cat apiserver 
KUBE_API_ARGS=&quot;--service-account-key-file=/root/fk/conf/serviceaccount.key --etcd-servers=http://192.168.106.237:2379 --insecure-bind-address=0.0.0.0 --insecure-port=9090 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2&quot;

去掉SecurityContextDeny

[root@managementa conf]# cat apiserver 
KUBE_API_ARGS=&quot;--service-account-key-file=/root/fk/conf/serviceaccount.key --etcd-servers=http://192.168.106.237:2379 --insecure-bind-address=0.0.0.0 --insecure-port=9090 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2&quot;

重启apiserver
[root@managementa conf]# systemctl restart kube-apiserver

</code></pre><ul>
<li>E1108 05:13:57.600996       6 config.go:428] Expected to load root CA config from /var/run/secrets/kubernetes.io/serviceaccount/ca.crt, but got err: open /var/run/secrets/kubernetes.io/serviceaccount/ca.crt: no such file or directory<br />
这个估计是没有指定api-server参数导致的，他默认使用https</li>
</ul>
<pre><code>[root@managementa ~]# kubectl get secrets --namespace=kube-system
NAME                  TYPE                                  DATA   AGE
default-token-w7j7z   kubernetes.io/service-account-token   2      3d3h
[root@managementa ~]# kubectl describe secret default-token-w7j7z --namespace=kube-system
Name:         default-token-w7j7z
Namespace:    kube-system
Labels:       &lt;none&gt;
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: 1c90a9c9-cc82-48cd-b740-dce6f717743f

Type:  kubernetes.io/service-account-token

Data
====
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImNUOUx4V2hVR0FtQ1J5V08wWnQxSU5mTEFsRzZrMUdDZ1drZTNYQllmVTAifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXc3ajd6Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxYzkwYTljOS1jYzgyLTQ4Y2QtYjc0MC1kY2U2ZjcxNzc0M2YiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.JrT-8Pj_ZhRndd8hb4wngBf7BEWWcLxjvGmNGotkKdhkPz2fKk-IUzoMqvG90rgOe70j1Ru5W0R5p6G0ryOBNzMZovBhZ3Na4Fhr8nJO8vAag995QkRxqek0LCyaAG1Vl7drxhnNgQUG-7W-TlZPs4XtfjDQDkQeNr87B5A-VOKd7vjWDKDdLY_XDFLvh4ykA-NO_ZJAegi21I3yvbbcCJNzWQwwLwoIFZiM8o5DMouVPOlsqbazs-svfp0y933YUOjUp9iR6IiNVQjAlqc1_RNpATVfgu9wzNlbwUOI6F8h4hXh-PH6Wg4GKcU1xGugskZhoQbJ5iBoUfa8CWxCBg
[root@managementa ~]# curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
[root@managementa ~]# tar -xzvf easy-rsa.tar.gz 
[root@managementa ~]# cd easy-rsa-master/easyrsa3/
[root@managementa easyrsa3]# ./easyrsa init-pki
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /root/easy-rsa-master/easyrsa3/pki

[root@managementa easyrsa3]# ./easyrsa --batch &quot;--req-cn=192.168.106.117@`date +%s`&quot; build-ca nopass
Generating a 2048 bit RSA private key
............................+++
...................................................+++
writing new private key to '/root/easy-rsa-master/easyrsa3/pki/private/ca.key'
-----

[root@managementa easyrsa3]# ./easyrsa --subject-alt-name=&quot;IP:192.168.106.117&quot; build-server-full server nopass
Generating a 2048 bit RSA private key
..............................+++
................+++
writing new private key to '/root/easy-rsa-master/easyrsa3/pki/private/server.key'
-----
Using configuration from /root/easy-rsa-master/easyrsa3/openssl-1.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :PRINTABLE:'server'
Certificate is to be certified until Nov  5 06:21:34 2029 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated
[root@managementa easyrsa3]# 

[root@managementa easyrsa3]# mkdir /root/fk/pki
[root@managementa easyrsa3]# cp pki/ca.crt pki/issued/server.crt pki/private/server.key /root/fk/pki/
[root@managementa easyrsa3]# 
[root@managementa easyrsa3]# chmod 644 /root/fk/pki/*
[root@managementa easyrsa3]# 
分别修改apiserver和controller-manager配置文件，添加如下参数
KUBE_API_ARGS=&quot;--client-ca-file=/root/fk/pki/ca.crt --tls-cert-file=/root/fk/pki/server.crt --tls-private-key-file=/root/fk/pki/server.key&quot;

KUBE_CONTROLLER_MANAGER_ARGS=&quot;--service_account_private_key_file=/root/fk/pki/server.key --root-ca-file=/root/fk/pki/ca.crt&quot;


[root@managementa conf]# cat apiserver 
KUBE_API_ARGS=&quot;--service-account-key-file=/root/fk/conf/serviceaccount.key --etcd-servers=http://192.168.106.237:2379 --insecure-bind-address=0.0.0.0 --insecure-port=9090 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --client-ca-file=/root/fk/pki/ca.crt --tls-cert-file=/root/fk/pki/server.crt --tls-private-key-file=/root/fk/pki/server.key&quot;

[root@managementa conf]# cat controller-manager 
KUBE_CONTROLLER_MANAGER_ARGS=&quot;--service-account-private-key-file=/root/fk/conf/serviceaccount.key --master=http://127.0.0.1:9090 --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --service-account-private-key-file=/root/fk/pki/server.key --root-ca-file=/root/fk/pki/ca.crt&quot; 

[root@managementa conf]# 
先不要重启apiserver和controller-manager
[root@managementa conf]# kubectl get secrets --all-namespaces
NAMESPACE         NAME                                       TYPE                                  DATA   AGE
default           default-token-9qp87                        kubernetes.io/service-account-token   2      3d5h
ingress-nginx     default-token-nl2c7                        kubernetes.io/service-account-token   2      4h15m
ingress-nginx     nginx-ingress-serviceaccount-token-kg58m   kubernetes.io/service-account-token   2      4h15m
kube-node-lease   default-token-6pnnc                        kubernetes.io/service-account-token   2      3d5h
kube-public       default-token-p8fnv                        kubernetes.io/service-account-token   2      3d5h
kube-system       default-token-w7j7z                        kubernetes.io/service-account-token   2      3d5h
[root@managementa conf]# systemctl stop kube-controller-manager
[root@managementa conf]# kubectl delete secret default-token-9qp87
secret &quot;default-token-9qp87&quot; deleted
[root@managementa conf]# kubectl delete secret default-token-nl2c7 --namespace=ingress-nginx
secret &quot;default-token-nl2c7&quot; deleted
[root@managementa conf]# kubectl delete secret default-token-6pnnc --namespace=kube-node-lease
secret &quot;default-token-6pnnc&quot; deleted
[root@managementa conf]# kubectl delete secret default-token-p8fnv --namespace=kube-public
secret &quot;default-token-p8fnv&quot; deleted
[root@managementa conf]# kubectl delete secret default-token-w7j7z --namespace=kube-system
secret &quot;default-token-w7j7z&quot; deleted
[root@managementa conf]# kubectl get secrets --all-namespaces
NAMESPACE       NAME                                       TYPE                                  DATA   AGE
ingress-nginx   nginx-ingress-serviceaccount-token-kg58m   kubernetes.io/service-account-token   2      4h18m
[root@managementa conf]# 
[root@managementa conf]# systemctl restart kube-apiserver
[root@managementa conf]# systemctl start  kube-controller-manager


[root@managementa conf]# kubectl get secrets --all-namespaces
NAMESPACE         NAME                                       TYPE                                  DATA   AGE
default           default-token-bb7jq                        kubernetes.io/service-account-token   3      22s
ingress-nginx     default-token-7k8jl                        kubernetes.io/service-account-token   3      22s
ingress-nginx     nginx-ingress-serviceaccount-token-kg58m   kubernetes.io/service-account-token   3      4h22m
kube-node-lease   default-token-hk4ck                        kubernetes.io/service-account-token   3      22s
kube-public       default-token-hkmpx                        kubernetes.io/service-account-token   3      22s
kube-system       default-token-z5mzv                        kubernetes.io/service-account-token   3      22s
[root@managementa conf]# kubectl describe secrets default-token-hkmpx -n kube-public
Name:         default-token-hkmpx
Namespace:    kube-public
Labels:       &lt;none&gt;
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: 082c7ee9-7f38-4f12-8ee0-cc1d23ebfd37

Type:  kubernetes.io/service-account-token

Data
====
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImJpVTZrLVVFa3ViUTcwOF9Dam5CX1ZNdDE5OWNrRG1yek52VHpiN2w4cEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXB1YmxpYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLWhrbXB4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIwODJjN2VlOS03ZjM4LTRmMTItOGVlMC1jYzFkMjNlYmZkMzciLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1wdWJsaWM6ZGVmYXVsdCJ9.eefwvqPYb22ydbDWbCVElLXqHG_xU_qsJ7ucLs5Ths1v1PDksK-PR3RKHv9a88LWp8zgxB-VoyFP95koI3V7-NsZjhKww6I7Y0g4NqnWw7G1x2GMd7nW0KpElFW0kN5gI-0cXz-cFLbypOZiYEbkzQsSDmeMwnycKwfyjIa5Yqltyc3Dkh-3Hcy3adu0K0AhzDJR1Wo3lfsOTYF4FhKn4teAfL3BmhMZq_usgj5fPq9kLh41dEh5J0Eo4F7h3aE8sYVfJl5vq02T7ZC4N5kMHEb0ZJsqP8CdSvDxd3S2ttRDjXh8UG0qnNBLz6SJ1XHNPOIMFZMzaXp25WGhLAwFXQ
ca.crt:     1233 bytes


重建
[root@managementa workdir]# kubectl delete -f mandaroty.yaml 
namespace &quot;ingress-nginx&quot; deleted
configmap &quot;nginx-configuration&quot; deleted
configmap &quot;tcp-services&quot; deleted
configmap &quot;udp-services&quot; deleted
serviceaccount &quot;nginx-ingress-serviceaccount&quot; deleted
clusterrole.rbac.authorization.k8s.io &quot;nginx-ingress-clusterrole&quot; deleted
role.rbac.authorization.k8s.io &quot;nginx-ingress-role&quot; deleted
rolebinding.rbac.authorization.k8s.io &quot;nginx-ingress-role-nisa-binding&quot; deleted
clusterrolebinding.rbac.authorization.k8s.io &quot;nginx-ingress-clusterrole-nisa-binding&quot; deleted
deployment.apps &quot;nginx-ingress-controller&quot; deleted
[root@managementa workdir]# kubectl create -f mandaroty.yaml       
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
[root@managementa workdir]# 
</code></pre><h4 id="ingress服务安装">ingress服务安装</h4>
<pre><code>[root@managementa workdir]# vi ingress-nginx.yaml
##vim ingress-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      nodePort: 1080
      port: 80
      targetPort: 80
      protocol: TCP
    - name: https
      nodePort: 1443
      port: 443
      targetPort: 443
      protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
[root@managementa workdir]# kubectl create -f ingress-nginx.yaml 
service/ingress-nginx created

安装完成

实例：
后端pod
[root@managementa ingress]# cat frontend-controller.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
 name: frontend
 labels:
  name: frontend
spec:
 replicas: 3
 selector:
  name: frontend
 template:
  metadata:
   labels:
    name: frontend
  spec:
   containers:
   - name: frontend
     image: kubeguide/guestbook-php-frontend
     env:
     - name: GET_HOSTS_FROM
       value: env
     ports:
     - containerPort: 80
后端service
[root@managementa ingress]# cat frontend-service.yaml 
apiVersion: v1
kind: Service
metadata:
 name: frontend
 labels:
  name: frontend
spec:
 ports:
 - name: http
   port: 80
   targetPort: 80
   
 selector:
  name: frontend
创建ingress  
[root@managementa ingress]# cat ingress-frontend.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-frontend
  namespace: default
  annotations:
    kubernets.io/ingress.class: &quot;nginx&quot;
spec:
  rules:
  - http:
    #host: frontend.default.svc.cluster.local 访问这个服务时使用的域名，请组合nginx+server_name详细了解，nginx 根据 server_name 匹配 HTTP 请求头的 host，去决定使用那个 server。host的值浏览器默认填写域名。如果所有server_name都匹配不到就使用默认的server，所以写个这个是最靠谱的。
      paths:
      - path:
        backend:
          serviceName: frontend
          servicePort: 80

[root@managementa ingress]# 

</code></pre><h3 id="k8s测试环境配置">k8s测试环境配置</h3>
<pre><code>[root@managementa fk]# ls
bin  conf  dns-test  ingress  kube-dashboard  kube-dns  kube-metrics-server  pki
[root@managementa fk]# cd conf
[root@managementa conf]# ls
apiserver  bootstrap.kubeconfig  controller-manager  kubelet  proxy  scheduler
[root@managementa conf]# cat kubelet 
KUBELET_ARGS=&quot;--kubeconfig=/root/fk/conf/bootstrap.kubeconfig --cluster-dns=169.169.169.169 --cluster-domain=cluster.local --hostname-override=192.168.106.118 --logtostderr=false --log-dir=/var/log/kubernetes --v=2&quot;

[root@managementa conf]# cat proxy 
KUBE_PROXY_ARGS=&quot;--master=http://192.168.106.117:9090 --hostname-override=192.168.106.118 --logtostderr=false --log-dir=/var/log/kubernetes --v=2&quot;
[root@managementa conf]# cat scheduler
KUBE_SCHEDULER_ARGS=&quot;--master=http://127.0.0.1:9090 --logtostderr=false --log-dir=/var/log/kubernetes --v=2&quot;
[root@managementa conf]# cat bootstrap.kubeconfig
apiVersion: v1
clusters:
- cluster:
    server: http://192.168.106.117:9090
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubelet-bootstrap
  name: default
current-context: default
kind: Config
preferences: {}
users: []
[root@managementa conf]# cat controller-manager 
KUBE_CONTROLLER_MANAGER_ARGS=&quot;--master=http://127.0.0.1:9090 --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --service-account-private-key-file=/root/fk/pki/kubernetes-key.pem --root-ca-file=/root/fk/pki/ca.pem&quot; 
[root@managementa conf]# cat apiserver 
KUBE_API_ARGS=&quot;--allow-privileged=true --enable-aggregator-routing=true --authorization-mode=RBAC --etcd-servers=http://192.168.106.237:2379 --insecure-bind-address=0.0.0.0 --insecure-port=9090 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --client-ca-file=/root/fk/pki/ca.pem --tls-cert-file=/root/fk/pki/kubernetes.pem --tls-private-key-file=/root/fk/pki/kubernetes-key.pem --requestheader-client-ca-file=/root/fk/pki/ca.pem --proxy-client-cert-file=/root/fk/pki/kubernetes.pem --proxy-client-key-file=/root/fk/pki/kubernetes-key.pem --requestheader-allowed-names= --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User&quot;

[root@managementa fk]# pwd
/root/fk
[root@managementa fk]# cat PodSecurityPolicy.yaml 
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: privileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
  privileged: true
  allowPrivilegeEscalation: true
  allowedCapabilities:
  - '*'
  volumes:
  - '*'
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  hostIPC: true
  hostPID: true
  runAsUser:
    rule: 'RunAsAny'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'

</code></pre><h3 id="ingress配置dashboard">ingress配置dashboard</h3>
<pre><code>
[root@managementa fk]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls.key -out ./tls.crt -subj &quot;/CN=dashboard-server&quot;
[root@managementa fk]# kubectl -n kubernetes-dashboard  create secret tls k8s-dashboard-secret --key ./tls.key --cert ./tls.crt

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-passthrough: &quot;true&quot;
  creationTimestamp: &quot;2019-11-22T03:21:03Z&quot;
  generation: 12
  name: dashboard
  namespace: kubernetes-dashboard
  resourceVersion: &quot;1712047&quot;
  selfLink: /apis/extensions/v1beta1/namespaces/kubernetes-dashboard/ingresses/dashboard
  uid: 8d33834a-41f2-42b1-b25b-0146fab7304d
spec:
  rules:
  - host: dashboard-server
    http:
      paths:
      - backend:
          serviceName: kubernetes-dashboard
          servicePort: 8443
        path: /
  tls:
  - secretName: k8s-dashboard-secret
</code></pre>
    </article>
    
    <script>
  'use strict';
  
  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  (function () {
    var singleContentsElem = document.querySelector('.single__contents');
    singleContentsElem ? 
    singleContentsElem.querySelectorAll('pre > code').forEach(function(elem) {
      var dataLang = elem.getAttribute('data-lang');
      var dataLangWrapper = document.createElement('div');
      var code = null;
      var codeTitle = null;

      if (dataLang && dataLang.includes(':')) {
        code = dataLang.split(':')[0];
        codeTitle = dataLang.split(':')[1];

        dataLangWrapper.className = 'language-' + code;
        dataLangWrapper.setAttribute('data-lang', codeTitle);

        elem.className = 'language-' + code;
        elem.setAttribute('data-lang', codeTitle);
        elem.setAttribute('id', codeTitle);
      } else if (!dataLang) {
        dataLangWrapper.setAttribute('data-lang', 'Code');
        dataLangWrapper.className = 'language-code';
      }

      if (!dataLang || codeTitle) {
        wrap(elem.parentNode, dataLangWrapper);
      }

    }) : null;
  })();

  var langCodeElem = document.querySelectorAll('.language-code');
  langCodeElem ? langCodeElem.forEach(function (elem) {
    var newElem = document.createElement('span');
    newElem.className = 'copy-to-clipboard';
    newElem.setAttribute('title', 'Copy to clipboard');
    elem.append(newElem);
  }) : null;
  
</script>
    
    
    
<div class="whoami__gutter"></div>
<hr class="hr-slash whoami-hr"/>
<section class="whoami">
  <div class="whoami__image-wrapper">
    
    
      
        <img data-src="/images/whoami/avatar.jpg" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" alt="月冰升" class="lazyload whoami__image"/>
      
    
  </div>
  <div class="whoami__contents">
    <div class="whoami__written-by">
      作者
    </div>
    <div class="whoami__title">
      
        月冰升
      
    </div>
    <div class="whoami__desc">
      
        Shaddy
      
    </div>
    <div class="whoami__social">
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </div>
  </div>
</section>
<hr class="hr-slash whoami-hr" />


    <section class="related">
    
    
    <h1 class="related__title">
      <hr class="hr-dots"/>
      <div>
        相关内容
      </div>
      <hr class="hr-dots"/>
    </h1>
    <ul class="related-ul">
        
        <li>
          <a href="/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/openvswitch2.7-%E5%AE%89%E8%A3%85/" class="related__link">openvswitch2.7 安装</a>
        </li>
        
        <li>
          <a href="/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/ip/" class="related__link">IP报文</a>
        </li>
        
        <li>
          <a href="/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s-%E9%9B%86%E7%BE%A4%E5%AE%89%E8%A3%85/" class="related__link">k8s 集群安装</a>
        </li>
        
        <li>
          <a href="/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/docker%E5%AE%89%E8%A3%85%E4%B8%8E%E9%9A%8F%E7%AC%94/" class="related__link">docker安装与随笔</a>
        </li>
        
    </ul>
    
  </section>
    <div class="grow"></div>
<nav class="pagination-single">
  
    
      <a href="http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/docker-%E9%83%A8%E7%BD%B2%E7%AC%94%E8%AE%B0/" class="pagination-single__left">
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"/></svg>
        </div>
        <div class="pagination-single__left-title">docker 部署笔记</div>      
      </a>
    
    <div class="grow"></div>
    
      <a href="http://shaddy.gitee.io/zh/linux/linux%E5%B7%A5%E5%85%B7/https%E8%AE%A4%E8%AF%81%E6%B5%81%E7%A8%8B/" class="pagination-single__right">      
        <div class="pagination-single__right-title">https认证流程</div>
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M5 13h11.17l-4.88 4.88c-.39.39-.39 1.03 0 1.42.39.39 1.02.39 1.41 0l6.59-6.59c.39-.39.39-1.02 0-1.41l-6.58-6.6c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L16.17 11H5c-.55 0-1 .45-1 1s.45 1 1 1z"/></svg>
        </div>
      </a>
    
  
</nav>
    
  

    <div class="modal micromodal-slide" id="modal" aria-hidden="true">
  <div class="modal__overlay" tabindex="-1" data-micromodal-close>
    <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
      
      <div class="modal__content" id="modal-content">
        <div id="mySwipe" class="swipe">
          <div class="swipe-wrap">
          </div>
        </div>
      </div>

      <span class="modal__items">
        
        <span class="modal__header">
          <div class="modal__paging" title="Page Info" aria-label="Current Page">
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--close" title="Close" aria-label="Close Button" data-micromodal-close>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="25" height="25"><path fill="currentColor" d="M 21.734375 19.640625 L 19.636719 21.734375 C 19.253906 22.121094 18.628906 22.121094 18.242188 21.734375 L 13 16.496094 L 7.761719 21.734375 C 7.375 22.121094 6.746094 22.121094 6.363281 21.734375 L 4.265625 19.640625 C 3.878906 19.253906 3.878906 18.628906 4.265625 18.242188 L 9.503906 13 L 4.265625 7.761719 C 3.882813 7.371094 3.882813 6.742188 4.265625 6.363281 L 6.363281 4.265625 C 6.746094 3.878906 7.375 3.878906 7.761719 4.265625 L 13 9.507813 L 18.242188 4.265625 C 18.628906 3.878906 19.257813 3.878906 19.636719 4.265625 L 21.734375 6.359375 C 22.121094 6.746094 22.121094 7.375 21.738281 7.761719 L 16.496094 13 L 21.734375 18.242188 C 22.121094 18.628906 22.121094 19.253906 21.734375 19.640625 Z"/></svg>
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--full" title="Full Screen" aria-label="Full Screen Button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="25" height="25"><path fill="currentColor" d="M 5 3 C 3.9069372 3 3 3.9069372 3 5 L 3 8 A 1.0001 1.0001 0 1 0 5 8 L 5 5 L 8 5 A 1.0001 1.0001 0 1 0 8 3 L 5 3 z M 16 3 A 1.0001 1.0001 0 1 0 16 5 L 19 5 L 19 8 A 1.0001 1.0001 0 1 0 21 8 L 21 5 C 21 3.9069372 20.093063 3 19 3 L 16 3 z M 3.984375 14.986328 A 1.0001 1.0001 0 0 0 3 16 L 3 19 C 3 20.093063 3.9069372 21 5 21 L 8 21 A 1.0001 1.0001 0 1 0 8 19 L 5 19 L 5 16 A 1.0001 1.0001 0 0 0 3.984375 14.986328 z M 19.984375 14.986328 A 1.0001 1.0001 0 0 0 19 16 L 19 19 L 16 19 A 1.0001 1.0001 0 1 0 16 21 L 19 21 C 20.093063 21 21 20.093063 21 19 L 21 16 A 1.0001 1.0001 0 0 0 19.984375 14.986328 z"/></svg>
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--normal" title="Normal Screen" aria-label="Normal Screen Button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="25" height="25"><path fill="currentColor" d="M 16.96875 4.972656 C 15.867188 4.988281 14.984375 5.894531 15 7 L 15 15 L 7 15 C 6.277344 14.988281 5.609375 15.367188 5.246094 15.992188 C 4.878906 16.613281 4.878906 17.386719 5.246094 18.007813 C 5.609375 18.632813 6.277344 19.011719 7 19 L 19 19 L 19 7 C 19.007813 6.460938 18.796875 5.941406 18.414063 5.558594 C 18.03125 5.175781 17.511719 4.964844 16.96875 4.972656 Z M 32.96875 4.972656 C 31.921875 4.988281 31.0625 5.8125 31.003906 6.859375 C 31 6.90625 31 6.953125 31 7 L 31 19 L 43 19 C 43.066406 19 43.132813 19 43.199219 18.992188 C 44.269531 18.894531 45.070313 17.972656 45.015625 16.902344 C 44.964844 15.828125 44.074219 14.988281 43 15 L 35 15 L 35 7 C 35.007813 6.460938 34.796875 5.941406 34.414063 5.558594 C 34.03125 5.175781 33.511719 4.964844 32.96875 4.972656 Z M 7 31 C 6.277344 30.988281 5.609375 31.367188 5.246094 31.992188 C 4.878906 32.613281 4.878906 33.386719 5.246094 34.007813 C 5.609375 34.632813 6.277344 35.011719 7 35 L 15 35 L 15 43 C 14.988281 43.722656 15.367188 44.390625 15.992188 44.753906 C 16.613281 45.121094 17.386719 45.121094 18.007813 44.753906 C 18.632813 44.390625 19.011719 43.722656 19 43 L 19 31 Z M 31 31 L 31 43 C 30.988281 43.722656 31.367188 44.390625 31.992188 44.753906 C 32.613281 45.121094 33.386719 45.121094 34.007813 44.753906 C 34.632813 44.390625 35.011719 43.722656 35 43 L 35 35 L 43 35 C 43.722656 35.011719 44.390625 34.632813 44.753906 34.007813 C 45.121094 33.386719 45.121094 32.613281 44.753906 31.992188 C 44.390625 31.367188 43.722656 30.988281 43 31 Z"/></svg>
          </div>
        </span>
        
        <div class="modal__icon modal__arrow modal__arrow--left" title="Arrow Left" aria-label="Arrow Left Button">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="28" height="28"><path fill="currentColor" d="M 23.28125 11 L 10 10 L 10 6.851563 C 10 6.523438 9.839844 6.277344 9.519531 6.03125 C 9.199219 5.949219 8.878906 5.949219 8.640625 6.113281 C 5.359375 8.410156 2.238281 12.257813 2.160156 12.421875 C 2.082031 12.578125 2.007813 12.8125 2.003906 12.976563 C 2.003906 12.980469 2 12.988281 2 12.992188 C 2 13.15625 2.078125 13.402344 2.160156 13.484375 C 2.238281 13.648438 5.28125 17.507813 8.640625 19.804688 C 8.960938 19.96875 9.28125 20.050781 9.519531 19.886719 C 9.839844 19.722656 10 19.476563 10 19.148438 L 10 16 L 23.28125 15 C 23.679688 14.679688 24 13.875 24 12.992188 C 24 12.195313 23.761719 11.320313 23.28125 11 Z"/></svg>
        </div>
        
        <div class="modal__icon modal__arrow modal__arrow--right" title="Arrow Right" aria-label="Arrow Right Button">

          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="28" height="28"><path fill="currentColor" d="M 2.71875 11.023438 L 16 10.023438 L 16 6.875 C 16 6.546875 16.160156 6.300781 16.480469 6.054688 C 16.800781 5.972656 17.121094 5.972656 17.359375 6.136719 C 20.640625 8.433594 23.761719 12.28125 23.839844 12.445313 C 23.917969 12.601563 23.992188 12.835938 23.996094 13 C 23.996094 13.003906 24 13.011719 24 13.015625 C 24 13.179688 23.921875 13.425781 23.839844 13.507813 C 23.761719 13.671875 20.71875 17.53125 17.359375 19.828125 C 17.039063 19.992188 16.71875 20.074219 16.480469 19.910156 C 16.160156 19.746094 16 19.5 16 19.171875 L 16 16.023438 L 2.71875 15.023438 C 2.320313 14.703125 2 13.898438 2 13.015625 C 2 12.21875 2.238281 11.34375 2.71875 11.023438 Z"/></svg>
        </div>

        <div class="modal__caption">
          <div class="modal__caption--text">
          </div>
        </div>

      </span>
    </div>
  </div>
</div>


<script defer src="/js/swipe.min.08ff2be1b74347bad9e267f732f1388d271b2f9d97b6a8a87bd6a510f17c5ad2.js"></script>

<script defer src="/js/micromodal.min.de01b44b2f383056bbcaf6ee921fd385d79108ec1129afd0eb2f3f5a07e11f45.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function () {
  
   
  var docElem = document.documentElement;

   
  function openFullscreen() {
    if (docElem.requestFullscreen) {
      docElem.requestFullscreen();
    } else if (docElem.mozRequestFullScreen) {  
      docElem.mozRequestFullScreen();
    } else if (docElem.webkitRequestFullscreen) {  
      docElem.webkitRequestFullscreen();
    } else if (docElem.msRequestFullscreen) {  
      docElem.msRequestFullscreen();
    }
  }

   
  function closeFullscreen() {
    if (document.fullscreenElement ||
      document.webkitFullscreenElement ||
      document.mozFullScreenElement) {
      if (document.exitFullscreen) {
        document.exitFullscreen();
      } else if (document.mozCancelFullScreen) {  
        document.mozCancelFullScreen();
      } else if (document.webkitExitFullscreen) {  
        document.webkitExitFullscreen();
      } else if (document.msExitFullscreen) {  
        document.msExitFullscreen();
      }
    }
  }

  var modal = document.getElementById('modal');
  var galleryContainerElem = document.querySelector('.gallery__container');
  var swipeWrapElem = document.querySelector('.swipe-wrap');
  var mySwipeElem = document.getElementById('mySwipe');
  var arrowLeftElem = document.querySelector('.modal__arrow--left');
  var arrowRightElem = document.querySelector('.modal__arrow--right');
  var closeElem = document.querySelector('.modal__toolbar--close');
  var fullElem = document.querySelector('.modal__toolbar--full');
  var normalElem = document.querySelector('.modal__toolbar--normal');
  var captionElem = document.querySelector('.modal__caption');
  var pagingElem = document.querySelector('.modal__paging');
  var itemsElem = document.querySelector('.modal__items');
  var imgTotalNum = null;
  var myFadeTimeout = null;
  var mySwipe = null;
  var keydownFunction = function (e) {
    if (e.key === 'ArrowRight') {
      if (modal && modal.classList.contains('is-open')) {
        mySwipe.next();
      }
    } else if (e.key === 'ArrowLeft') {
      if (modal && modal.classList.contains('is-open')) {
        mySwipe.prev();
      }
    }
  }

  if (galleryContainerElem) {
    imgTotalNum = galleryContainerElem.querySelectorAll('img').length;
  } else {
    galleryContainerElem = document.querySelector('.single__contents');
    imgTotalNum = galleryContainerElem.querySelectorAll('img').length;
  }

  MicroModal.init({
    onClose: function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
        closeFullscreen();
      }
      window.removeEventListener('keydown', keydownFunction);
    },
    disableScroll: true,
    disableFocus: true,
    awaitOpenAnimation: false,
    awaitCloseAnimation: false,
    debugMode: false,
  });

  var imageLoad = function(src) {
    return new Promise(function(resolve, reject) {
      var newImg = new Image;
      newImg.onload = function() {
        resolve(newImg);
      }
      newImg.onerror = reject;
      newImg.src = src;
    });
  }

  galleryContainerElem.querySelectorAll('img').forEach(function (elem, idx) {
    elem.style.cursor = 'pointer';

    var clonedElem = elem.cloneNode(true);
    clonedElem.style.maxHeight = '100%';
    clonedElem.style.maxWidth = '100%';
    clonedElem.onclick = function (e) {
      e.stopPropagation();
    }

    var wrapper = document.createElement('div');
    wrapper.style.width = '100%';
    wrapper.style.height = '100vh';
    wrapper.setAttribute('data-micromodal-close', '');
    wrapper.onclick = function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }
    }
    wrapper.onmouseenter = function () {
      clearTimeout(myFadeTimeout);
      fadeIn(itemsElem, 200);
    };
    wrapper.onmouseleave = function () {
      myFadeTimeout = setTimeout(function () {
        fadeOut(itemsElem, 200);
      }, 2500);
    }
    wrapper.ontouchstart = function() {
      fadeIn(itemsElem, 200);
    }
    wrapper.append(clonedElem);
    swipeWrapElem.append(wrapper);

    elem.addEventListener('click', async function (e) {
      MicroModal.show('modal');
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }

      var imgSrc = e.target.getAttribute('data-src') || e.target.getAttribute('src');
      var img = await imageLoad(imgSrc);
      clonedElem.style.width = img.width + 'px';
      clonedElem.style.height = img.height + 'px';
      
      
      mySwipe = new Swipe(mySwipeElem, {
        startSlide: idx,
        draggable: true,
        autoRestart: false,
        continuous: false,
        disableScroll: true,
        stopPropagation: true,
        callback: async function (index, element) {
          
          var imgElem = element.querySelector('img');
          var imgSrc = imgElem.getAttribute('data-src') || imgElem.getAttribute('src');
          var img = await imageLoad(imgSrc);
          imgElem.style.width = img.width + 'px';
          imgElem.style.height = img.height + 'px';

          
          if (captionElem && imgElem) {
            var caption = null;
            if (imgElem.getAttribute('data-caption')) {
              caption = imgElem.getAttribute('data-caption');
            } else if (imgElem.getAttribute('title')) {
              caption = imgElem.getAttribute('title');
            } else if (imgElem.getAttribute('alt')) {
              caption = imgElem.getAttribute('alt');
            } else {
              caption = imgElem.getAttribute('src');
            }

            captionElem.querySelector('.modal__caption--text').innerText = caption;
            pagingElem.innerText = (index + 1) + ' / ' + imgTotalNum;

            clearTimeout(myFadeTimeout);
            fadeIn(itemsElem, 200);
          }
        },
      });

      fadeIn(itemsElem);

      
      if (captionElem) {
        var caption = null;
        if (e.target.getAttribute('data-caption')) {
          caption = e.target.getAttribute('data-caption');
        } else if (e.target.getAttribute('title')) {
          caption = e.target.getAttribute('title');
        } else if (e.target.getAttribute('alt')) {
          caption = e.target.getAttribute('alt');
        } else {
          caption = e.target.getAttribute('src');
        }

        captionElem.querySelector('.modal__caption--text').innerText = caption;
        pagingElem.innerText = (idx + 1) + ' / ' + imgTotalNum;
      }

      if (normalElem && fullElem) {
        normalElem.style.zIndex = -1;
        normalElem.style.opacity = 0;
        fullElem.style.zIndex = 25;
        fullElem.style.opacity = 1;
      }
    });

    window.addEventListener('keydown', keydownFunction);
  });

  arrowLeftElem ?
    arrowLeftElem.addEventListener('click', function (e) {
      if (mySwipe) {
        mySwipe.prev();
      }
    }) : null;
  arrowRightElem ?
    arrowRightElem.addEventListener('click', function (e) {
      if (mySwipe) {
        mySwipe.next();
      }
    }) : null;

  closeElem ?
    closeElem.addEventListener('click', function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }
      closeFullscreen();
      MicroModal.close('modal');
    }) : null;

  fullElem ?
    fullElem.addEventListener('click', function (e) {
      openFullscreen();
      if (normalElem) {
        normalElem.style.zIndex = 25;
        normalElem.style.opacity = 1;
        fullElem.style.zIndex = -1;
        fullElem.style.opacity = 0;
      }
    }) : null;

  normalElem ?
    normalElem.addEventListener('click', function (e) {
      closeFullscreen();
      if (fullElem) {
        fullElem.style.zIndex = 25;
        fullElem.style.opacity = 1;
        normalElem.style.zIndex = -1;
        normalElem.style.opacity = 0;
      }
    }) : null;
  
});
</script>

    <div class="hide">
      

<div class="search">
  <span class="icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  </span>
  <input id="search" aria-label="Site Search" class="input" type="text" placeholder="搜索" autocomplete="off">
  <div id="search-results" class="dropdown">
    <div id="search-menu" class="dropdown-menu" role="menu">
    </div>
  </div>
</div>


    </div>
  </div>
</main>


<aside class="single__side main-side">
  


<section class="sidebar hide">
  <script>document.querySelector('.sidebar').classList.remove('hide')</script>
  <div class="toc__flexbox" data-position="fixed">
    <h6 class="toc__title" data-ani="true">目录</h6>
    
      <label class="switch" data-ani="true">
        <input id="toggle-toc" aria-label="Toggle TOC" type="checkbox" checked>
        <span class="slider round"></span>
      </label>
    
  </div>
  <div class="toc " data-dir="ltr" data-folding="false" data-ani="true">
    <nav id="TableOfContents">
  <ul>
    <li>
      <ul>
        <li><a href="#flannel在docker中安装">flannel在docker中安装</a></li>
        <li><a href="#k8s-ca证书部署">k8s ca证书部署</a></li>
        <li><a href="#k8s-dns安装">k8s DNS安装</a></li>
        <li><a href="#dashboard-安装">Dashboard 安装</a></li>
        <li><a href="#metrics-server安装k8s从17版本开始引入metrics-server替代heapster">metrics server安装(K8S从1.7版本开始引入metrics server替代heapster)</a></li>
        <li><a href="#ingress安装">Ingress安装</a></li>
        <li><a href="#k8s测试环境配置">k8s测试环境配置</a></li>
        <li><a href="#ingress配置dashboard">ingress配置dashboard</a></li>
      </ul>
    </li>
  </ul>
</nav>
  </div>
</section>



</aside>

<script>
  
  
  

  var enableToc = JSON.parse("true");
  var toc = JSON.parse("null");
  var tocPosition = JSON.parse("\"inner\"");
  
  var singleMainElem = document.querySelector('.single__main');
  var singleSideElem = document.querySelector('.single__side');

  enquire.register("screen and (max-width: 769px)", {
    match: function () {
      if ((enableToc || toc) && tocPosition !== "outer") {
        if (singleMainElem && singleSideElem) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
          singleSideElem.classList.remove('main-side');
          singleSideElem.classList.add('hide');
        }
      } else if (tocPosition === "outer") {
        if (singleMainElem && !singleMainElem.classList.contains('main-main')) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
        }
        if (singleSideElem && !singleSideElem.classList.contains('hide')) {
          singleSideElem.classList.add('hide');
        }
      }
    },
    unmatch: function () {
      if ((enableToc || toc) && tocPosition !== "outer") {
        singleMainElem.classList.remove('main');
        singleMainElem.classList.add('main-main');
        singleSideElem.classList.remove('hide');
        singleSideElem.classList.add('main-side');
      } else if (tocPosition === "outer") {
        if (singleMainElem && !singleMainElem.classList.contains('main-main')) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
        }
        if (singleSideElem && !singleSideElem.classList.contains('hide')) {
          singleSideElem.classList.add('hide');
        }
      }

      var navCollapseBtn = document.querySelector('.navbar__burger');
      var navCollapse = document.getElementsByClassName('navbarm__collapse')[0];
      if (navCollapse) {
        navCollapse.setAttribute('data-open', false);
        navCollapse.style.maxHeight = 0;
        navCollapseBtn.classList.remove('is-active');
      }
      document.getElementsByClassName('navbar__menu')[0].classList.remove('is-active');
      document.getElementsByClassName('mobile-search')[0].classList.add('hide');
    },
    setup: function () { },
    deferSetup: true,
    destroy: function () { },
  });
</script>




<script defer src="/js/clipboard.min.1626706afc88d95ebe1173b553ec732c6dc82a576989315fdf5e7779af738a44.js"></script>

<script defer src="/js/helper/getParents.min.js"></script>

<script defer src="/js/helper/closest.min.js"></script>

<script defer src="/js/helper/prev.min.js"></script>

<script defer src="/js/helper/prop.min.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>

















<script>
  'use strict';

  window.onload = function() {
    var navbar = document.querySelector('.navbar');
    var singleContentsElem = document.querySelector('.single__contents');

    
    
    
    var enableBusuanzi = JSON.parse("false");
    var busuanziPagePV = JSON.parse("true");
    
    if (enableBusuanzi && busuanziPagePV) {
      var pagePvElem = document.querySelector('#busuanzi_value_page_pv');
      pagePvElem.textContent = pagePvElem.textContent.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
    }    
    


    
    
    
    
    
    
    var enableToc = JSON.parse("true");
    var toc = JSON.parse("null");
    var hideToc = JSON.parse("false");
    var tocFlexbox = document.querySelector('.toc__flexbox');
    var tocFlexboxOuter = document.querySelector('.toc__flexbox--outer');
    var tocFolding = JSON.parse("null");
    
    if ((enableToc || toc) && document.querySelector('.toc')) {
      var tableOfContentsElem = document.querySelector('.toc').querySelector('#TableOfContents');

      if (false === tocFolding) {

      } else {
        tableOfContentsElem.querySelectorAll('ul') ?
          tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
            rootUl.querySelectorAll('li').forEach(function (liElem) {
              liElem.querySelectorAll('ul').forEach(function (ulElem) {
                ulElem.style.display = 'none';
              });
            });
          }) : null;
      }

      if (tableOfContentsElem) {
        if (tableOfContentsElem.querySelectorAll('a').length > 0) {
          tableOfContentsElem.querySelectorAll('a').forEach(function (elem) {
            elem.addEventListener('click', function () {
              var id = elem.getAttribute('id');
              navbar.classList.remove('navbar--show');
              navbar.classList.remove('navbar--hide');
              navbar.classList.add('navbar--hide');

              document.querySelector('.toc').querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              elem.classList.add('active');

              var curElem = tableOfContentsElem.querySelector('[href="#' + id + '"]');
              if (curElem && curElem.nextElementSibling) {
                curElem.nextElementSibling.style.display = 'block';
              }
              if (curElem) {
                getParents(curElem, 'ul') ?
                  getParents(curElem, 'ul').forEach(function (elem) {
                    elem.style.display = 'block';
                  }) : null;
              }
            });
          });
        } else {
          if (tocFlexbox) {
            tocFlexbox.setAttribute('data-position', '');
            if (!tocFlexbox.classList.contains('hide')) {
              tocFlexbox.classList.add('hide');
            }
          }
          if (tocFlexboxOuter) {
            tocFlexboxOuter.setAttribute('data-position', '');
            if (!tocFlexboxOuter.classList.contains('hide')) {
              tocFlexboxOuter.classList.add('hide');
            }
          }
        }
      }

      
      var toggleTocElem = document.getElementById("toggle-toc");
      var visibleTocElem = document.getElementById('visible-toc');
      var tocElem = document.querySelector('.toc');
      var mainElem = document.querySelector('main');
      var sideElem = document.querySelector('side');
      var tocFlexboxElem = document.querySelector('.toc__flexbox');

      toggleTocElem ? 
      toggleTocElem.addEventListener('change', function(e) {
        if (e.target.checked) {
          if (tocElem) {
            fadeIn(tocElem, 200);
          }
          if (tocFlexboxElem) {
            tocFlexboxElem.setAttribute('data-position', 'fixed');
          }

          if (mainElem) {
            mainElem.classList.remove('main-main');
            mainElem.classList.remove('main');
            mainElem.classList.add('main-main');
          }
          if (sideElem) {
            sideElem.classList.remove('main-side');
          }
        } else {
          if (tocElem) {
            fadeOut(tocElem, 200);
          }
          if (tocFlexboxElem) {
            tocFlexboxElem.setAttribute('data-position', 'absolute');
          }

          if (mainElem) {
            mainElem.classList.remove('main-main');
            mainElem.classList.remove('main');
            mainElem.classList.add('main');
          }
          if (sideElem) {
            sideElem.classList.remove('main-side');
          }
        }
      }) : null;

      visibleTocElem ?
      visibleTocElem.addEventListener('change', function(e) {
        if (e.target.checked) {
          if (tocElem) {
            fadeIn(tocElem, 200);
          }
        } else {
          if (tocElem) {
            fadeOut(tocElem, 200);
          }
        }
      }) : null;
    }
    


    
    var tables = document.querySelectorAll('.single__contents > table');
    for (let i = 0; i < tables.length; i++) {
      var table = tables[i];
      var wrapper = document.createElement('div');
      wrapper.className = 'table-wrapper';
      table.parentElement.replaceChild(wrapper, table);
      wrapper.appendChild(table);
    }
    


    
    var text, clip = new ClipboardJS('.anchor');
    var headers = singleContentsElem.querySelectorAll("h1, h2, h3, h4");

    
    var languagedir = JSON.parse("\"ltr\"");

    headers ? 
    headers.forEach(function (elem) {
      var url = encodeURI(document.location.origin + document.location.pathname);
      var link = url + "#" + elem.getAttribute('id');
      var newElemOuter = document.createElement('span');
      newElemOuter.classList.add('anchor');
      newElemOuter.classList.add('hide');
      newElemOuter.setAttribute('data-clipboard-text', link);
      newElemOuter.style.position = 'relative';

      var newElemInner = document.createElement('span');
      newElemInner.style.fontSize = '1rem';
      newElemInner.style.position = 'absolute';
      newElemInner.style.top = '50%';
      newElemInner.style.transform = 'translateY(-50%)';
      newElemInner.innerText = "🔗";

      if (languagedir === "rtl") {
        newElemInner.style.left = '-2rem';
      } else {
        newElemInner.style.right = '-2rem';
      }

      newElemOuter.append(newElemInner);
      elem.append(newElemOuter);

      elem.addEventListener('mouseenter', function() {
        this.querySelector('.anchor').classList.remove('hide');
      });
      elem.addEventListener('mouseleave', function () {
        this.querySelector('.anchor').classList.add('hide');
      });
    }) : null;

    document.querySelectorAll('.anchor').forEach(function(elem) {
      elem.addEventListener('mouseleave', function() {
        elem.setAttribute('aria-label', null);
        elem.classList.remove('tooltipped');
        elem.classList.remove('tooltipped-s');
        elem.classList.remove('tooltipped-w');
      });
    });

    clip.on('success', function (e) {
      e.clearSelection();
      e.trigger.setAttribute('aria-label', 'Link copied to clipboard!');
      e.trigger.classList.add('tooltipped');
      e.trigger.classList.add('tooltipped-s');
    });
    


    
    var clipInit = false;
    var preChromaElem = document.querySelectorAll('pre.chroma');
    var langCodeElem = document.querySelectorAll('.language-code');
    var dollarCodeElem = document.querySelectorAll('div.language-\\$');
    var gtCodeElem = document.querySelectorAll('div.language-\\>');

    var makeClipboard = function(elem) {
      var code = elem,
        text = elem.textContent;
        
      if (text.length > 15) {
        if (!clipInit) {
          var text, clip = new ClipboardJS('.copy-to-clipboard', {
            text: function (trigger) {
              var codeElem = prev(trigger).querySelectorAll('code');
              if (codeElem.length > 1) {
                text = prev(trigger).querySelector('code[class^="language-"]').textContent;
              } else {
                text = prev(trigger).querySelector('code').textContent;
              }

              return text.replace(/^\$\s/gm, '');
            }
          });

          var inPre;
          clip.on('success', function (e) {
            e.clearSelection();
            inPre = prop(e.trigger.parentNode, 'tagName') == 'PRE';
            e.trigger.setAttribute('aria-label', 'Copied to clipboard!');
            e.trigger.classList.add('tooltipped');
            e.trigger.classList.add('tooltipped-w');
          });

          clip.on('error', function (e) {
            inPre = prop(e.trigger.parentNode, 'tagName') == 'PRE';
            e.trigger.setAttribute('aria-label', e.action.toString());
            e.trigger.classList.add('tooltipped');
            e.trigger.classList.add('tooltipped-w');
          });

          clipInit = true;
        }

        var notAllowedClass = ['language-mermaid', 'language-viz', 'language-wave', 'language-chart', 'language-msc', 'language-flowchart'];
        var isNotAllowedIncluded = false;
        var curClassName = code.getAttribute('class');

        for (var i = 0; i < notAllowedClass.length; i++) {
          if (curClassName && curClassName.startsWith(notAllowedClass[i])) {
            isNotAllowedIncluded = true;
            break;
          }
        }

        if (!isNotAllowedIncluded) {
          if (curClassName) {
            var newClipboardElem = document.createElement('span');
            newClipboardElem.setAttribute('class', 'copy-to-clipboard');
            newClipboardElem.setAttribute('title', 'Copy to clipboard');
            elem.parentNode.parentNode.insertBefore(newClipboardElem, elem.parentNode.nextElementSibling);
          }
        }
      }
    }

    var makeSymbolClipboard = function(elem) {
      var clipboardSpan = document.createElement('span');
      clipboardSpan.setAttribute('class', 'copy-to-clipboard');
      clipboardSpan.setAttribute('title', 'Copy to clipboard');
      elem.parentNode.parentNode.insertBefore(clipboardSpan, elem.parentNode.nextElementSibling);
    }

    preChromaElem ? 
    preChromaElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function(codeElem) {
        makeClipboard(codeElem);
      });
    }) : null;
    
    langCodeElem ? 
    langCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeClipboard(codeElem);
      });
    }) : null;

    dollarCodeElem ? 
    dollarCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeSymbolClipboard(codeElem);
      });
    }) : null;

    gtCodeElem ?
    gtCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeSymbolClipboard(codeElem);
      });
    }) : null;
    


    
    dollarCodeElem ?
    dollarCodeElem.forEach(function(elem) {
      var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
      lnts ? 
      lnts.forEach(function(lnt) {
        lnt.innerHTML = '$<br/>';
      }) : null;
    }) : null;

    gtCodeElem ?
    gtCodeElem.forEach(function(elem) {
      var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
      lnts ? 
      lnts.forEach(function(lnt) {
        lnt.innerHTML = '><br/>';
      }) : null;
    }) : null;
    


    
    
    var lib = JSON.parse("null");

    if (lib && lib.includes('mermaid')) {
      
      var themeVariant = localStorage.getItem('theme') || JSON.parse("\"dark\"");

      if (themeVariant === "dark" || themeVariant === "hacker") {
        mermaid.initialize({ theme: 'dark' });
      } else {
        mermaid.initialize({ theme: 'default' });
      }
      
      var mermaids = [];
      [].push.apply(mermaids, document.getElementsByClassName('language-mermaid'));
      mermaids.forEach(function(elem) {
        var elemParentNode = elem.parentNode;

        if (elemParentNode !== document.body) {
          elemParentNode.parentNode.insertBefore(elem, elemParentNode);
          elemParentNode.parentNode.removeChild(elemParentNode);
        }

        var newElemWrapper = document.createElement('div');
        newElemWrapper.classList.add('mermaid');
        newElemWrapper.style.padding = '34px 4px 6px';
        newElemWrapper.innerHTML = elem.innerHTML;
        elem.replaceWith(newElemWrapper);
      });
    }
    
    

    
    if (lib && lib.includes('katex')) {
      var mathElements = document.getElementsByClassName('math');
      var options = {
        delimiters: [
          { left: "$$", right: "$$", display: true },
          { left: "\\[", right: "\\]", display: true },
          { left: "$", right: "$", display: false },
          { left: "\\(", right: "\\)", display: false }
        ],
      };

      renderMathInElement(document.querySelector('.single__contents'), options);
    }
    


    
    if (lib && lib.includes('flowchartjs')) {
      
      var options = JSON.parse("{\"arrow-end\":\"block\",\"element-color\":\"black\",\"fill\":\"white\",\"flowstate\":{\"approved\":{\"fill\":\"#58C4A3\",\"font-size\":12,\"no-text\":\"n/a\",\"yes-text\":\"APPROVED\"},\"current\":{\"fill\":\"yellow\",\"font-color\":\"red\",\"font-weight\":\"bold\"},\"future\":{\"fill\":\"#FFFF99\"},\"invalid\":{\"fill\":\"#444444\"},\"past\":{\"fill\":\"#CCCCCC\",\"font-size\":12},\"rejected\":{\"fill\":\"#C45879\",\"font-size\":12,\"no-text\":\"REJECTED\",\"yes-text\":\"n/a\"},\"request\":{\"fill\":\"blue\"}},\"font-color\":\"black\",\"font-size\":14,\"line-color\":\"black\",\"line-length\":50,\"line-width\":3,\"no-text\":\"no\",\"scale\":1,\"symbols\":{\"end\":{\"class\":\"end-element\"},\"start\":{\"element-color\":\"green\",\"fill\":\"yellow\",\"font-color\":\"red\"}},\"text-margin\":10,\"x\":0,\"y\":0,\"yes-text\":\"yes\"}");
      var jsonContent = null;

      var flowchartPrefix = "language-flowchart";
      var index = 0;
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + flowchartPrefix + "]"), function(x){
          x.style.display = 'none'
          x.parentNode.style.backgroundColor = "transparent"
          jsonContent = x.innerText;

          var node0 = document.createElement('div');
          node0.id = 'flowchart' + index;
          x.parentNode.insertBefore(node0, x);

          var diagram = flowchart.parse(jsonContent);
          diagram.drawSVG("flowchart"+index, options);

          index +=1;
      });      
    }
    


    
    


    
    if (lib && lib.includes('msc')) {
      
      var options = JSON.parse("{\"theme\":\"hand\"}");
      var jsonContent = null;

      var index = 0;
      var chartPrefix = "language-msc";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('div');
        node0.id = 'msc' + index;
        x.parentNode.insertBefore(node0, x);
        var diagram = Diagram.parse(jsonContent);
        diagram.drawSVG("msc" + index, options);
        index += 1;
      });
    }
    


    
    if (lib && lib.includes('chart')) {
      var borderColor = "#666";
      var bgColor = "#ddd";
      var borderWidth = 2;

      Chart.defaults.global.elements.rectangle.borderWidth = borderWidth;
      Chart.defaults.global.elements.rectangle.borderColor = borderColor;
      Chart.defaults.global.elements.rectangle.backgroundColor = bgColor;

      Chart.defaults.global.elements.line.borderWidth = borderWidth;
      Chart.defaults.global.elements.line.borderColor = borderColor;
      Chart.defaults.global.elements.line.backgroundColor = bgColor;

      Chart.defaults.global.elements.point.borderWidth = borderWidth;
      Chart.defaults.global.elements.point.borderColor = borderColor;
      Chart.defaults.global.elements.point.backgroundColor = bgColor;

      var chartPrefix = "language-chart";
      var index = 0;
      var jsonContent = null;

      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('canvas');
        var source = null;
        node0.height = 200;
        node0.style.height = 200;
        node0.id = 'myChart' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        var ctx = document.getElementById('myChart' + index).getContext('2d');
        var myChart = new Chart(ctx, source);
        index += 1;
      });            
    }
    


    
    if (lib && lib.includes('wavedrom')) {
      var wavePrefix = "language-wave";
      var index = 0;
      var jsonContent = null;
      
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + wavePrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('div');
        var source = null;
        node0.id = 'WaveDrom_Display_' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        WaveDrom.RenderWaveForm(index, source, "WaveDrom_Display_");
        index += 1;
      });
    }
    


    
    if (lib && lib.includes('viz')) {
      var vizPrefix = "language-viz-";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + vizPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        var engine;
        x.getAttribute("class").split(" ").forEach(function (cls) {
          if (cls.startsWith(vizPrefix)) {
            engine = cls.substr(vizPrefix.length);
          }
        });
        var viz = new Viz();
        viz.renderSVGElement(x.innerText, { engine: engine })
          .then(function (element) {
            element.style.width = "100%";
            x.parentNode.insertBefore(element, x);
          })
      });
    }
    
    
  }
</script>


            
            <footer class="footer">
    
<div class="dropdown">
  <button class="dropdown-trigger" aria-label="Select Theme Button">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12.65 15.67c.14-.36.05-.77-.23-1.05l-2.09-2.06.03-.03c1.74-1.94 2.98-4.17 3.71-6.53h1.94c.54 0 .99-.45.99-.99v-.02c0-.54-.45-.99-.99-.99H10V3c0-.55-.45-1-1-1s-1 .45-1 1v1H1.99c-.54 0-.99.45-.99.99 0 .55.45.99.99.99h10.18C11.5 7.92 10.44 9.75 9 11.35c-.81-.89-1.49-1.86-2.06-2.88-.16-.29-.45-.47-.78-.47-.69 0-1.13.75-.79 1.35.63 1.13 1.4 2.21 2.3 3.21L3.3 16.87c-.4.39-.4 1.03 0 1.42.39.39 1.02.39 1.42 0L9 14l2.02 2.02c.51.51 1.38.32 1.63-.35zM17.5 10c-.6 0-1.14.37-1.35.94l-3.67 9.8c-.24.61.22 1.26.87 1.26.39 0 .74-.24.88-.61l.89-2.39h4.75l.9 2.39c.14.36.49.61.88.61.65 0 1.11-.65.88-1.26l-3.67-9.8c-.22-.57-.76-.94-1.36-.94zm-1.62 7l1.62-4.33L19.12 17h-3.24z"/></svg>
  </button>
  <div class="dropdown-content">
    
    
    
      
      
        
      
        
      
        
        
          
            
              <a href="http://shaddy.gitee.io/zh/linux/linux%E8%99%9A%E6%8B%9F%E5%8C%96/k8s%E6%89%A9%E5%B1%95%E6%8F%92%E4%BB%B6/" data-lang="zh" class="dropdown-item is-active">中文</a>
            
          
        
      
    
  </div>
</div>

    
<div class="footer__social">
  <div class="social">
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
            
    
    
  
  
    
      <a href="http://shaddy.gitee.io/zh/linux//index.xml" type="application/rss+xml" title="RSS" aria-label="RSS Feed Link">
        <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><circle fill="currentColor" cx="6.18" cy="17.82" r="2.18"/><path fill="currentColor" d="M5.59 10.23c-.84-.14-1.59.55-1.59 1.4 0 .71.53 1.28 1.23 1.4 2.92.51 5.22 2.82 5.74 5.74.12.7.69 1.23 1.4 1.23.85 0 1.54-.75 1.41-1.59-.68-4.2-3.99-7.51-8.19-8.18zm-.03-5.71C4.73 4.43 4 5.1 4 5.93c0 .73.55 1.33 1.27 1.4 6.01.6 10.79 5.38 11.39 11.39.07.73.67 1.28 1.4 1.28.84 0 1.5-.73 1.42-1.56-.73-7.34-6.57-13.19-13.92-13.92z"/></svg>
      </a>
    
  

  </div>
</div>

    
<div id="gtt">
  <div class="gtt">
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 14.71L12 10.83l3.88 3.88c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L12.7 8.71c-.39-.39-1.02-.39-1.41 0L6.7 13.3c-.39.39-.39 1.02 0 1.41.39.38 1.03.39 1.42 0z"/></svg>
  </div>
</div>

    <hr />

    <div class="basicflex">
        
    </div>

    <div class="footer__poweredby">
        
                
            <p class="caption">
                
                    ©2020, All Rights Reserved
                
            </p>
        

        
            <p class="caption">Powered by <a href="https://gohugo.io/" target="_blank" rel="noreferrer">Hugo</a> and the <a href="https://github.com/zzossig/hugo-theme-zzo" target="_blank" rel="noreferrer">Zzo theme</a></p>
        
        
    </div> 
</footer>
        </div>
        





<div class="wrapper__right hide" data-pad="true" dir="ltr">
  <script>document.querySelector('.wrapper__right').classList.remove('hide')</script>
  
</div>

    </div>
</body>

</html>